本文仅作学习记录,不作他用!
头文件
#include "opencv2/core/core.hpp"
//新式C++风格的结构以及数学运算
#include "openCv2/flann/mini刊ann.hpp"
//最邻近搜索匹配函数
#include "openCV2/imgproc/imgproc.hpp"
//新式C++风格图像处理函数
#include "openCV2/video/photo.hpp"
//操作和恢复照片相关算法
#include "openCv2/video/video.hpp"
//视觉追踪以及背景分割
#include "opencv2/features2d/features2d.hpp"
//用于追踪的二维特征
#include "openCV2/objdetect/objdetect.hpp"
//级联人脸分类器、latent SVM分类器、HoG特征和平面片检测器
#include "opencv2/calib3d/calib3d.hpp"
//校准以及双目视觉相关
#include "opencv2/ml/ml.hpp"
//机器学习、聚类以及模式识别相关
#include "opencv2/highgui/highgui.hpp"
//新式C++风格的显示、滑动条、鼠标操作以及输入输出相关
#include "opencv2/contrib/contrib.hpp"
- 使用头文件opencv.hpp来包含所有可能在OpenCV 函数中用到的头文件,会使得编译速度较慢,根据需求选择需要的函数的头文件将降低编译时间。
- 头文件在…lmodules/…/include文件夹
- 函数对应的源文件也存在于对应的src文件夹中 …lmodules/…/include/src
网络资源:
OpenCV库概述
OpenCV3 概述
第一个程序:显示图片
#include <opencv2/opencv.hpp> //Include ftle for every supported OpenCV function
int main(int argc, char** argv ) {
cv::Mat img = cv::imread(argv[1], -1);
if (img.empty()) return -1;
cv::namedWindow("Example1", cv::WINDOW_AUTOSIZE);
cv::imshow("Example1", img);
cv::waitKey(0);
cv::destroyWindow("Example1");
return 0;
}
函数前加上c v: : ,向编译器说明你所调用的函数处于cv命名空间。若想简化使用use namespace cv
但是,若不想发生于其他库同名函数发生冲突,建议使用cv::
,并一起为标准,使代码风格统一。
第二个程序:视频
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
#include "string"
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
cv::namedWindow("Example3", cv::WINDOW_AUTOSIZE);
cv::VideoCapture cap;
cap.open(string(argv[1]));
cv::Mat frame;
for (;;) {
cap >> frame;
if (frame.empty()) break;
cv::imshow("Example3", frame);
if (cv::waitKey(33) >= 0) break;
}
return 0;
}
cap.open(string(argv[1]));
改为“````cap.open(0)```即可调用摄像头
视频跳转
添加一个滑动条,使得用户可以进行视频跳转。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <fstream>
using namespace std;
int g_slider_position = 0; //存储滑动条位置
int g_run = 1; //新的跳转触发后会置零。当它为正的时候,指示在停止之前程序要播放多少张图片;当它为负的时候,表示系统处于连续视频播放模式。
int g_dontset = 0; //start out in single step mode
cv::VideoCapture g_cap;
void onTrackbarSlide(int pos, void*) {
g_cap.set(cv::CAP_PROP_POS_FRAMES, pos);
if (!g_dontset)
g_run = 1;
g_dontset = 0;
}
int main(int arc, char** argv) {
cv::namedWindow("Example2_4", cv::WINDOW_AUTOSIZE);
g_cap.open("C:/Users/zhoum/Pictures/视频项目/south_gate.mp4");
int frames = (int)g_cap.get(cv::CAP_PROP_FRAME_COUNT);
int tmpw = (int)g_cap.get(cv::CAP_PROP_FRAME_WIDTH);
int tmph = (int)g_cap.get(cv::CAP_PROP_FRAME_HEIGHT);
cout << "video has " << frames << " frames of dimensions(" << tmpw << ", " << tmph << ")." << endl;
cv::createTrackbar("Position", "Example2_4", &g_slider_position, frames,
onTrackbarSlide);
cv::Mat frame;
for (;;) {
if (g_run != 0) {
g_cap >> frame;
if (frame.empty()) break;
int current_pos = (int)g_cap.get(cv::CAP_PROP_POS_FRAMES);
g_dontset = 1;
cv::setTrackbarPos("Position", "Example2_4", current_pos);
cv::imshow("Example2_4", frame);
g_run = 1;
}
char c = (char)cv::waitKey(10);
// single step
if (c == 's'){
g_run = 1; cout << "Single step, run = " << g_run << endl;
}
// run mode
if (c == 'r') {
g_run = -1; cout << "Run mode, run = " << g_run << endl;
}
if (c == 27)
break;
}
return 0;
}
简单的变换
加载图像并且在显示之前平滑处理图像。
#include <opencv2/opencv.hpp>
int main() {
cv::Mat image = cv::imread("C:/Users/.../.../10.png", -1);
// 创建窗口,显示输入\输出
cv::namedWindow("Example2_5-in", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Example2_5-out", cv::WINDOW_AUTOSIZE);
// 创建窗口,显示输入图片
cv::imshow("Example2_5-in", image);
// 创建图片保存平滑后的图片
cv::Mat out;
// 开始平滑
cv::GaussianBlur(image, out, cv::Size(5, 5), 3, 3);
cv::GaussianBlur(out, out, cv::Size(5, 5), 3, 3);
cv::imshow("Example2_5-out", out);
cv::waitKey(0);
return 0;
}
较复杂的变换
降采样、灰度图、边缘分割
#include <opencv2/opencv.hpp>
int main(int argc, char** argv) {
cv::Mat img1, img2, img_gry, img_cny;
img1 = cv::imread("C://Users//zhoum//Desktop//1.jpg", -1);
cv::namedWindow("Example1", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Example2", cv::WINDOW_AUTOSIZE);
cv::imshow("Example1", img1);
//下采样一半
cv::pyrDown(img1, img2);
cv::imshow("Example2", img2);
//转化灰度图
cv::cvtColor(img1, img_gry, cv::COLOR_BGR2GRAY);
cv::namedWindow("Example gray", cv::WINDOW_AUTOSIZE);
cv::imshow("Example gray", img_gry);
//canny边缘分割
cv::Canny(img_gry, img_cny, 50, 150, 3, true);
cv::namedWindow("Example canny", cv::WINDOW_AUTOSIZE);
cv::imshow("Example canny", img_cny);
cv::waitKey(0);
return 0;
}
写入AVI文件
OpenCV提供的格式是未经过压缩的,目前支持的格式如下:
CV_FOURCC('P', 'I', 'M', '1') = MPEG-1 codec
CV_FOURCC('M', 'J', 'P', 'G') = motion-jpeg codec
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
CV_FOURCC('U', '2', '6', '3') = H263 codec
CV_FOURCC('I', '2', '6', '3') = H263I codec
CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char* argv[]) {
cv::namedWindow("Example_11", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Log_Polar", cv::WINDOW_AUTOSIZE);
//调用摄像头
cv::VideoCapture capture(0);
double fps = capture.get(cv::CAP_PROP_FPS);
cv::Size size(
(int)capture.get(cv::CAP_PROP_FRAME_WIDTH),
(int)capture.get(cv::CAP_PROP_FRAME_HEIGHT)
);
cv::VideoWriter writer;
writer.open("output_video.avi", CV_FOURCC('M', 'J', 'P', 'G'), fps, size);
cv::Mat logpolar_frame, bgr_frame;
for (;;) {
capture >> bgr_frame;
if (bgr_frame.empty()) break;
cv::imshow("Example2_11", bgr_frame);
cv::logPolar(
bgr_frame, //输入
logpolar_frame, //输出
//logpolar转换的中心点
cv::Point2f(
bgr_frame.cols / 2,
bgr_frame.rows / 2
),
40, //幅值(比例参数)
cv::WARP_FILL_OUTLIERS // 用0值填满外部
);
cv::imshow("Log_Polar", logpolar_frame);
writer << logpolar_frame;
char c = cv::waitKey(10);
if (c == 27) break; //允许用户中断
}
capture.release();
}
练习
- 1.安装编译OpenCv
- 2.运行lkdemo.cpp
- 3.读取视频降采样并存储彩色视频
- 4.给练习3增加显示处理过图像的功能
- 5.增加滑动条,通过滑动条来调节降采样率,显示处理后结果。存储功能跳过。
个人能力有限,代码可能存在部分问题,请批评指正
根据书本内容大致完成了练习的作业。
运行lkdemo.cpp
初始化
黑夜模式
降采样并存储
问题与解决:
Q:按照书里面存储的代码和降采样直接结合,输出的视频无法播放。
A:设置cv::VideoWriter writer;
的size
时,原来代码是读取视频大小获得,如不修改和采样后的视频大小不符合,故需要将尺寸修改为采样后大小,这里由于是2倍降采样,直接将size
减半就行。
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char* argv[]) {
cv::namedWindow("original_img", cv::WINDOW_AUTOSIZE);
cv::namedWindow("sampled_img", cv::WINDOW_AUTOSIZE);
//调用摄像头
cv::VideoCapture capture(0);
double fps = capture.get(cv::CAP_PROP_FPS);
// 降采样后视频尺寸变为原来一半,故除以2
cv::Size size(
(int)capture.get(cv::CAP_PROP_FRAME_WIDTH) / 2,
(int)capture.get(cv::CAP_PROP_FRAME_HEIGHT) / 2
);
cv::VideoWriter writer;
writer.open("sampled_video.avi", CV_FOURCC('M', 'J', 'P', 'G'), fps, size);
cv::Mat original_frame, sampled_frame;
for (;;) {
capture >> original_frame;
if (original_frame.empty()) break;
cv::imshow("original_img", original_frame);
cv::pyrDown(original_frame, sampled_frame);
cv::imshow("sampled_img", sampled_frame);
writer << sampled_frame;
char c = cv::waitKey(10);
if (c == 27) break; //允许用户中断
}
capture.release();
}
滑动条调节降采样率
问题与解决:
-
cv::Szie()
报错
pyrDown()函数一次只能下采样一半,尺寸不能随意设置
-
slide
不显示
A:
未在使用createTrackbar()前为指定窗口
cv::namedWindow("Slide", cv::WINDOW_AUTOSIZE);
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <fstream>
using namespace std;
int slider_position = 0;
int sample_multiple = 0;
void onTrackbarSlide(int pos, void*) {
if (pos % 2 == 0) sample_multiple = pos;
}
int main(int arc, char** argv) {
cv::VideoCapture capture(0);
cv::namedWindow("original_video", cv::WINDOW_AUTOSIZE);
cv::namedWindow("sampled_video", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Slide", cv::WINDOW_AUTOSIZE);
cv::createTrackbar("Position", "Slide", &slider_position, 8,
onTrackbarSlide);
cv::Mat original_frame, sampled_frame;
for (;;) {
capture >> original_frame;
// pyrDown() 没只能下降一半,所以这样设置不行。
//cv::Size sample_size(
// (int)((original_frame.cols + 1) / sample_multiple),
// (int)((original_frame.rows + 1) / sample_multiple)
//);
if (original_frame.empty()) break;
cv::imshow("original_video", original_frame);
cout << "video downsample multiple: " << sample_multiple << endl;
sampled_frame = original_frame;
for (int i = 1; i < sample_multiple; i++) {
cv::pyrDown(original_frame, sampled_frame);
original_frame = sampled_frame;
}
cv::imshow("sampled_video", sampled_frame);
char c = cv::waitKey(10);
if (c == 27) break; //允许用户中断
}
return 0;
}
显示效果