OpenCV3入门基础

本文为学习 Learning OpenCV 3 Computer vision in C++ 第二章的笔记。

主要内容

涉及创建窗口并显示图片或播放视频;使用进度条控制视频播放;对图片进行处理(如模糊和边缘检测);保存视频。

窗口的生命周期

创建窗口
显示图片或视频:将数据传递到窗口。注意:OpenCV 中使用 Mat 类来表示图片,同时也用来表示视频中的每一帧。
刷新屏幕
销毁窗口 释放内存

namedWindow("Example1", WINDOW_NORMAL);
imshow("Example1", img);
waitKey(0);
destroyWindow("Example1");

读取图片文件

使用函数 imread 读取某个文件,并能制定读取方式(如保持原样,灰度等等):

Mat img = imread(argv[1], IMREAD_ANYCOLOR);

读取视频文件

需要使用到 VideoCapture 类,读取视频,然后将视频流一帧一帧的取出。除了读取文件,也可以读取摄像头——将文件路径换为0即可。

VideoCapture cap;
cap.open(argv[1], 0);
Mat frame;
for (;;) {
    cap >> frame;
    if (frame.empty()) break;
    //other action with the frame
}

给视频添加进度条

使用函数 createTrackbar 在某个窗口创建进度条,通过函数 setTrackbarPos 将进度条设定到指定位置。

图像处理

可以对图像连续进行多个操作,完成pipeline操作(Metal也有同样的操作机制)。

  • 使用 Gaussian Blur 和 pyramid;
  • 颜色空间转换:从3个channel转换成1个channel;实现灰度等等;
  • 边缘检测: Canney detect;

视频保存

例子11 是一个写视频的例子,在学习的过程中遇到了以下问题。 CV_FOURCC('M', 'J', 'P', 'G') 需要更新,OpenCV 3中使用 CAP_OPENCV_MJPEG,编译后运行如下命令:

./ex11 './test.avi' './mytest.mp4'

此时会报错: “OpenCV: FFMPEG: tag 0x00000898/'�???' is not found (format 'mp4 / MP4 (MPEG-4 Part 14)')'”。目测应该是和 codec 相关。查看了源文件中的注释:

With some backends fourcc=-1 pops up the codec selection dialog from the system.

于是设置 fourcc 为1 运行后,弹出系统上可以支持的codec

OpenCV: FFMPEG: format mp4 / MP4 (MPEG-4 Part 14)
fourcc tag 0x7634706d/'mp4v' codec_id 000C
fourcc tag 0x31637661/'avc1' codec_id 001B
fourcc tag 0x33637661/'avc3' codec_id 001B
fourcc tag 0x31766568/'hev1' codec_id 00AD
fourcc tag 0x31637668/'hvc1' codec_id 00AD
fourcc tag 0x7634706d/'mp4v' codec_id 0002
fourcc tag 0x7634706d/'mp4v' codec_id 0001
fourcc tag 0x7634706d/'mp4v' codec_id 0007
fourcc tag 0x7634706d/'mp4v' codec_id 003D
fourcc tag 0x7634706d/'mp4v' codec_id 0058
fourcc tag 0x312d6376/'vc-1' codec_id 0046
fourcc tag 0x63617264/'drac' codec_id 0074
fourcc tag 0x7634706d/'mp4v' codec_id 00A3
fourcc tag 0x39307076/'vp09' codec_id 00A7
fourcc tag 0x31307661/'av01' codec_id 801D
fourcc tag 0x6134706d/'mp4a' codec_id 15002
fourcc tag 0x6134706d/'mp4a' codec_id 1502D
fourcc tag 0x6134706d/'mp4a' codec_id 15001
fourcc tag 0x6134706d/'mp4a' codec_id 15000
fourcc tag 0x332d6361/'ac-3' codec_id 15003
fourcc tag 0x332d6365/'ec-3' codec_id 15028
fourcc tag 0x6134706d/'mp4a' codec_id 15004
fourcc tag 0x61706c6d/'mlpa' codec_id 1502C
fourcc tag 0x43614c66/'fLaC' codec_id 1500C
fourcc tag 0x7375704f/'Opus' codec_id 1503C
fourcc tag 0x6134706d/'mp4a' codec_id 15005
fourcc tag 0x6134706d/'mp4a' codec_id 15018
fourcc tag 0x6134706d/'mp4a' codec_id 15803
fourcc tag 0x7334706d/'mp4s' codec_id 17000
fourcc tag 0x67337874/'tx3g' codec_id 17005
fourcc tag 0x646d7067/'gpmd' codec_id 18807
fourcc tag 0x316d686d/'mhm1' codec_id 15817

接着,更新代码为 bool result = writer.open(argv[2], 0x7634706d, fps, size); 然后执行 ./ex11 './test.avi' './mytest.mp4' 后,顺利生成文件。

以上就是第二章的全部笔记。
需要源码的可以留言。

下一步

下一步考虑写个 makefile 或者自动创建 Xcode 项目——毕竟用的是 Mac OS X 啊。😄

遇到的问题

编译并运行

因为入门的程序比较简单,直接在 VS Code里编辑运行了,运行的时候使用命令如下:

clang -x c++ -target arm64-apple-macos12.3 ex01Image.cpp  -o ex01 -I /Users/account/miniforge3/pkgs/libopencv-4.5.5-py39h4853228_6/include/opencv4 -std=gnu++11 -L /Users/account/miniforge3/pkgs/libopencv-4.5.5-py39h4853228_6/lib -lopencv_highgui -lopencv_core -lopencv_imgcodecs -lstdc++ -L'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib' -Xlinker -rpath -Xlinker /Users/account/miniforge3/pkgs/libopencv-4.5.5-py39h4853228_6/lib -Xlinker -rpath -Xlinker /Users/account/miniforge3/envs/cv/lib

链接的时候,仅使用 -L 参数指定 OpenCV 相关的lib目录时,编译报错:

Library not loaded: @rpath/libprotobuf.30.dylib

还需要使用 -Xlinker -rpath -Xlinker /Users/account/miniforge3/pkgs/libopencv-4.5.5-py39h4853228_6/lib。之所以想到添加该选项,主要是参考了前一篇文章在 M1 Mac 上使用 OpenCV中对应的 Xcode 工程的编译命令。

关于 Xlinker 选项:

If you want to pass an option that takes a separate argument, you must use -Xlinker twice, once for the option and once for the argument. For example, to pass -assert definitions, you must write -Xlinker -assert -Xlinker definitions. It does not work to write -Xlinker "-assert definitions", because this passes the entire string as a single argument, which is not what the linker expects.

另外 还遇到错误

OpenCV 4.x+ requires enabled C++11 support

需要添加 -std=gnu++11

参考资料

https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html