shithole
学习opencv3中⽂版笔记
⼀些概念
计算机视觉:
将静⽌的图像,或者是视频转换成⼀个决策或者⼀种新的表达⽅式,这些转化都是为了达到⼀个⽬标。
且输⼊数据可以包含⼀些辅助信息,⽐如摄像机架在物品之上,激光扫描仪在⼀⽶处发现⼀个物体。
本质:把具有噪声成分的数值矩阵变成感知
英语加盟哪家好视觉问题的病态本质: 随着视点的变化,物体的⼆维外观会变化很⼤。同⼀张⼆维图像,可以表⽰多种三维场景。
具体的问题: 数据被噪声和形变影响。
[ ] ⼀些疑问点:
“⼀般来说不可能通过⽐较⼀个点和它紧密相连的点来检测图像⾥的边缘”,所以问题是如何进⾏边缘检测? 书中提到的“观察⼀个局部区域的统计特征,边缘检测会变得容易些”是什么意思呢?
positively
“由局部区域卷积的响应连成的点串,构成边缘” ⼜是什么意思呢?
opencv的结构和内容
opencv主体分为5个模块,
CV图像处理和视觉算法,
MLL统计分类器,
HighGUI图像和视频输⼊/输出,
CXCORE基本机构和算法+XML⽀持+绘图函数,
CvAux
HighGUI常⽤: ⾥⾯提供读取各种类型的图像⽂件,视频内容以及摄像机输⼊的功能。
安装配置opencv
踩坑1: 未找到依赖 dll⽂件
解决⽅式:
设置环境变量,Path中加⼊opencv/build/x64/bin的路径,然后重启!
踩坑2 :MFC和win32项⽬的区别?
⽬前还是不清楚,win32中包含许多基本的API,MFC中包含很多类库,可通过类库间接使⽤API
win32程序更加的底层,MFC程序可以调⽤win32?
踩坑3 : ⽆法打开元数据⽂件 “platform.winmd”yeepay
⾸先 元数据⽂件platform.winmd是什么?
解决⽅式就是重新创建了⼀下项⽬,莫名其妙的不再报错,有可能是在配置vs时debug和x64在对应配置⽬录时没有选择对应的选项。
踩坑4 cmake是⼲嘛的?
2-1 展⽰图⽚
#include<iostream>
碧昂斯怀孕#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat srcImg =imread("C://Urs//lfy//opencv//1.jpg");
namedWindow("Example1", WINDOW_AUTOSIZE);
imshow("Example1", srcImg);
四级几分及格waitKey(0);
return0;
}
踩坑1: 在加载某个图像时,出现未经处理的异常
解决⽅式:
认为是路径格式的问题 ,必须是:// ⽽不能是:\
2-2 播放视频
代码如下:
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
int main(int argc,char**argv){
namedWindow("exp2-3", cv::WINDOW_AUTOSIZE);
VideoCapture cap;
cap.open(string(argv[1]));
Mat frame;
for(;;){
cap >> frame;
pty())break;
bias// ran out of file
imshow("exp2-3", frame);
if(waitKey(33)>=0)break;
}
return0;
}
踩坑1:
如果直接运⾏程序会报错,因为argv[1]没有设定,会报strlen处的⼀个错误。
实际运⾏过程应该是右键项⽬->属性->调试->命令参数处填⼊相应的参数。
知识点:
1. 实例化VedioCapture类型是为了播放以及停⽌各种类型的视频
2. VedioCapture的open函数打开⼀个视频,然后定义⼀个Mat类型的frame,将vedio⼀帧帧导⼊frame,即 cap>>frame
3. waitKey()参数是秒数,可以控制视频播放每⼀帧之间的间隔
2-3 Moving around- 为视频增加⼀个slider tracker
操作: 按下s键,⼀步⼀步播放,按下R键,切换为流畅地播放
创建tracker,我们⽤到了createTrackbar()函数
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<fstream>
参数英文
using namespace std;
using namespace cv;
int g_slider_position =0;
int g_run =1, g_dontt =0;// start out in single step mode
VideoCapture g_cap;
void onTrackbarSlide(int pos,void*){
g_cap.t(CAP_PROP_POS_FRAMES, pos);// 将滑块对应的数值赋值给起始帧
if(!g_dontt)
g_run =1;
g_dontt =0;
// 但是如果这个回调函数被⽤户点击触发,此处使得在新的下⼀帧未到达时,保持单步模式。
// 具体g_dontt是什么意思还没有搞清楚,g_run是⼀个控制播放模式的变量,给g_run=1时表⽰单步播放即显⽰当前这⼀帧,g_run=-1时开始正常播放。}
int main(int argc,char** argv){
namedWindow("exp2-4", WINDOW_AUTOSIZE);
g_cap.open(string(argv[1]));
int frames =(int)(CAP_PROP_FRAME_COUNT);
int tmpw =(int)(CAP_PROP_FRAME_WIDTH);
int tmph =(int)(CAP_PROP_FRAME_HEIGHT);
cout <<" video has "<< frames <<"frames of dimensions("<< tmpw
<<","<< tmph <<")."<< endl;
createTrackbar("position","exp2-4",&g_slider_position,frames,onTrackbarSlide);
// createTrackbar的四个参数!
Mat frame;
for(;;){
// 当g_run=-1播放,当g_run=1只播放1帧图⽚
if(g_run !=0){
g_cap >> frame;
pty())break;
int current_pos =(int)(CAP_PROP_POS_FRAMES);
g_dontt =1;
tTrackbarPos("position","exp2-4", current_pos);
imshow("exp2-4", frame);
g_run -=1;
}
// 每播完⼀帧到如下程序,
// 如果此时g_run=1时,下次循环进⼊if后 g_run-=1 =>0,如果不按下r使g_run!=0,则视频不会再播放,单独显⽰下⼀帧
// 如果此时g_run=-1时,下次进⼊if后不断减⼀,⼀直不等于0则可以⼀直播放下⼀帧。
char c =(char)waitKey(10);
if(c =='s'){
g_run =1; cout <<"single step,run="<< g_run << endl;
}
if(c =='r'){
g_run =-1; cout <<"run mode,run="<< g_run << endl;
}
if(c ==27){
break;
}
}
return0;
}
createTrackbar的四个参数
tTrackbarPos的搭配使⽤
VideoCapture的get()⽅法
2-4 A Simple Transformation
smoothing an image, 通过⾼斯或者其他卷积运算,减少图像中的信息内容
下述程序的作⽤:在视频显⽰之前加载并且平滑图像
#include<opencv2/opencv.hpp>
using namespace cv;
培训私人教练
void example2_5(const Mat &image){
// 创建⼀些窗⼝去显⽰输⼊和输出图像
namedWindow("example2_5-in", WINDOW_AUTOSIZE);
namedWindow("example2_5-out1", WINDOW_AUTOSIZE);
namedWindow("example2_5-out2", WINDOW_AUTOSIZE);
imshow("example2_5-in", image);
Mat out;
// 平滑处理
GaussianBlur(image, out,Size(5,5),3,3);
// 被5*5的卷积核进⾏⾼斯滤波,且⾼斯核通常为奇数,为什么呢?忘记了...
imshow("example2_5-out1", out);
// 以下是第⼆次卷积所得
GaussianBlur(out, out,Size(5,5),3,3);
// 在输出窗⼝展⽰平滑后的图像
imshow("example2_5-out2", out);
waitKey(0);
}
int main(){
Mat srcImg=imread("C://Urs//lfy//opencv//1.jpg");
example2_5(srcImg);
return0;
}
踩坑1:异常: cv::Exception,位于内存位置…
本以为是传参的格式问题,看了半天发现是图⽚的路径写错的问题啦 !
2-5 A Not-SO-Simple Transformation
图像降采样,⽤到了pyrdown()函数,先将图像⾼斯模糊,再进⾏降采样。
pyrdown()函数
摘要:我们在对图像进⾏处理时,⼤多是要着眼于图像中有意义的部分,⽽同⼀幅图像中可能含有不同尺度下“有意义”的信息,为了充分利⽤这些图像信息,就需要对图像进⾏多尺度描述了。
/*
创造新的图像,是原图像长宽的⼀半
*/
#include<opencv2/opencv.hpp>
using namespace cv;
int main(){
Mat img1, img2;
namedWindow("exp1", WINDOW_AUTOSIZE);
namedWindow("exp2", WINDOW_AUTOSIZE);
img1 =imread("C://Urs//lfy//opencv//1.jpg");
imshow("exp1", img1);
pyrDown(img1, img2);
imshow("exp2", img2);
waitKey(0);
return0;
}
canny函数
/*
cv.candy 可以⽤于边缘检测,⾸先要把图像转换为单通道的图像,⽤cvtColor变为灰度图像
*/
#include<opencv2/opencv.hpp>
using namespace cv;
int main(){
Mat img_rgb, img_gry, img_cny;
namedWindow("exp gray", WINDOW_AUTOSIZE);
namedWindow("exp canny", WINDOW_AUTOSIZE);
img_rgb =imread("C://Urs//lfy//opencv//1.jpg");
cvtColor(img_rgb, img_gry, COLOR_BGR2GRAY);
imshow("exp gray", img_gry);
Canny(img_gry, img_cny,10,100,3,true);
imshow("exp canny", img_cny);
waitKey(0);
}
canny函数:
void cvCanny(const CvArr* image, CvArr* edges,double threshold1,double threshold2,int aperture_size=3);
参数image: 单通道输⼊图像
参数edges: 单通道存储边缘的输出图像
参数threshold1: 阈值1
参数threshold2: 阈值2
参数aperture_size: sobel算⼦的核⼤⼩
疑问:两个阈值中,⼩阈值控制边缘的连接,⼤阈值控制强边缘的分割?
美国大选辩论视频
2-6 Input from a camera
2-7 writing into an avi file: logPolar函数,调⽤了摄像头