c++ - Opencv 恢复到比我设置的分辨率更高的分辨率
问题描述
我在保存图像时遇到问题。我想从我不想在收到图像后调整图像大小开始,我希望网络摄像头以我的相机支持的本机较低分辨率开始。我在树莓派操作系统上。支持的分辨率。
pi@raspberrypi:~/Desktop $ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'YUYV' (YUYV 4:2:2)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 176x144
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 160x120
Interval: Discrete 0.033s (30.000 fps)
我尝试通过终端和我的 c++ 代码更改分辨率,如下所示。
在 C++ 中
stream.set(cv::CAP_PROP_FRAME_WIDTH, 320);
stream.set(cv::CAP_PROP_FRAME_HEIGHT, 240);
在终端中,我更改并检查了分辨率
pi@raspberrypi:~/Desktop $ v4l2-ctl -d0 --set-fmt-video=width=320,height=240
pi@raspberrypi:~/Desktop $ v4l2-ctl -d0 --get-fmt-video | egrep 'Pixel Format|Width/Height'
Width/Height : 320/240
Pixel Format : 'YUYV' (YUYV 4:2:2)
pi@raspberrypi:~/Desktop $ v4l2-ctl -d2 --set-fmt-video=width=320,height=240
pi@raspberrypi:~/Desktop $ v4l2-ctl -d2 --get-fmt-video | egrep 'Pixel Format|Width/Height'
Width/Height : 320/240
Pixel Format : 'YUYV' (YUYV 4:2:2)
pi@raspberrypi:~/Desktop $ v4l2-ctl -d4 --set-fmt-video=width=320,height=240
pi@raspberrypi:~/Desktop $ v4l2-ctl -d4 --get-fmt-video | egrep 'Pixel Format|Width/Height'
Width/Height : 320/240
Pixel Format : 'YUYV' (YUYV 4:2:2)
当我去运行我的代码时,它总是以 640x480 的更高分辨率保存。我为每个线程运行 3 个 pthread。代码本质上没有任何问题,它可以保存但分辨率更高。但是当我运行像 streamer -f jpeg -o image.jpeg 这样的东西时,它会正确保存
c++ 代码的简单示例,它不以 320/240 的分辨率保存,但它确实以 640x480 的分辨率保存。运行上面的 egrep 代码还会将宽度/高度显示为恢复到 640/480。所以我确信当我改变这些值时,OpenCV 的表现并不好。
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#include <iostream>
#include <fstream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>
int main(){
int i = 0;
cv::VideoCapture stream(0);
stream.set(cv::CAP_PROP_FRAME_WIDTH, 320);
stream.set(cv::CAP_PROP_FRAME_HEIGHT, 240);
cv::Mat3b Frame;
if(!stream.isOpened())
{
std::cout << "Cannot Open Camera: " + 0 + '\n';
}
else
{
std::cout << "Camera Open: " << 0 + '\n';
}
while (true)
{
stream.open(0);
const boost::posix_time::ptime now =
boost::posix_time::microsec_clock::local_time();
const boost::posix_time::time_duration td = now.time_of_day();
const long year = now.date().year();
const long month = now.date().month();
const long day = now.date().day();
const long hours = td.hours();
const long minutes = td.minutes();
const long seconds = td.seconds();
const long milliseconds = td.total_milliseconds() -
((hours * 3600 + minutes * 60 + seconds) * 1000);
char buf[80];
sprintf(buf, "%02ld%02ld%02ld_%02ld%02ld%02ld__%03ld",
year, month, day, hours, minutes, seconds, milliseconds);
std::string sBuf = buf;
std::string PATH = std::string("/home/pi/Desktop/") +
"camA" +
'/' +
"camA" +
'_' +
sBuf +
".jpeg";
stream.grab();
stream.retrieve(Frame);
cv::imwrite(PATH, Frame);
i++;
if (i == 1){
stream.release();
break;
}
}
}
任何想法我可以做些什么来解决这个问题?如果 OpenCV 允许,也许将 /dev/video* 更改为只读?
解决方案
我认为直接使用v4l2库api会更好。在此处查看完整示例:https ://gist.github.com/maxlapshin/1253534
为了设置宽度和高度,他们使用以下代码:
if (force_format) {
fprintf(stderr, "Set H264\r\n");
fmt.fmt.pix.width = 640; //replace
fmt.fmt.pix.height = 480; //replace
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264; //replace
fmt.fmt.pix.field = V4L2_FIELD_ANY;
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
errno_exit("VIDIOC_S_FMT");
/* Note VIDIOC_S_FMT may change width and height. */
}
您可以在那里设置自己的值。我建议你给自己一些时间来分析和测试这个例子。
推荐阅读
- javascript - 我们如何在 VueJS 中传递子元素
- sympy - 如何简化sympy中的等效方程?
- r - 稀疏 W 矩阵的特征向量空间滤波的空间回归?
- c# - 我尝试使用 ASP.NET Core Web API 登录时出现身份问题
- kotlin - 如何删除项目并将其替换为 ArrayList 中同一位置的新项目?
- pycharm - 如何禁用 Pycharm 的新 pytest 调试配置?
- javascript - 在 JavaScript 中打印主窗口中的数组并在 java 脚本中添加 css 代码
- r - 根据 R 中的条件将命名数据框索引提取到 2 列数组中
- python - 错误 event.type == pygame.KEYDOWN - NAME 错误的问题
- cmake - CMake:从时间戳组件中删除前导零