因为要参加老师的一个小项目,所以今天开始学习关于Opencv的内容,昨天刚刚配置好Opencv,是在Visual Studio2017上面配置的Opencv 3.4.1,如果大家配置的话,(因为后面博客中配置的版本为3.2.0,我们配置的版本为3.4.1,我们需要将最后一步中的"opencv_world320d.lib",换成“opencv_world341d.lib”即可)可以参考一下: https://blog.csdn.net/sinat_36264666/article/details/73135823?ref=myread
栗子2-1:
#include
#include
#include
#include
using namespace cv;
int main(int argc, char **argv)
{
IplImage *img = cvLoadImage("图片位置");
cvNamedWindow("Example1", 0);
cvShowImage("Example1", img);
cvWaitKey(0);
cvReleaseImage(&img);
cvDestroyWindow("Example1");
}
cvLoadImage函数:将图片加载到内存,函数通过文件名确定被加载文件的格式,并且该函数将自动分配图像数据结构所需要的内存,函数结束后返回一个指针,指针的类型为IplImage
cvNamedWindow函数:函数创建一个窗口,第一个参数为窗口的名称,后面如果用到这个窗口就可以调用他的名字,第二个参数可以是0,也可以是CV_WINDOW_AUTOSIZE,不同就是:0可以手动改变窗口的大小,CV_WINDOW_AUTOSIZE则不能手动更改窗口大小
cvShowImage函数:在一个已经创建好的窗口中显示img指向的图像,当再次被调用时,窗口会被重新绘制
cvWaitKey函数:参数可以是任意实数:0或者负数的时候,程序会一直等到用户触发(按下任意一个按键),否则程序会等待相应的ms数
cvReleaseImage cvDestoryWindow函数:分别释放相应的内存
栗子2-2
#include
#include
#include
#include
using namespace cv;
int main(int argc, char **argv)
{
cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE);
CvCapture* capture = cvCreateFileCapture("视频位置");
IplImage * frame;
while (1)
{
frame = cvQueryFrame(capture);
if (!frame) break;
cvShowImage("Example2", frame);
char c = cvWaitKey(33);
if (c == 27) break;
}
cvReleaseCapture(&capture);
cvDestroyWindow("Example2");
}
CvCreateFileCapture函数:通过参数确定AVI文件位置,返回一个指向CvCapture结构的指针,并且该指针会被初始化为对应AVI文件的开头
cvQueryFrame函数: 装载下一帧视频文件到内存,返回当前帧的指针,而且含住使用的是cvCapture中分配好的内存,所以就不需要通过cvReleaseCapture函数来释放空间
我们观察发现,cvWaitKey函数中参数为33,那么含义就是等到33ms,如果返回值为27(对应键盘中的ESC键),那么就会停止while循环,否则继续进行循环,那么也就是每一帧的效果都是通过固定的时间来进行更新的,我们可以通过cvCaptureFromCamera()函数 来对帧率进行更好地判定
栗子2-3
实现读取视频进度条的添加,这样的,我们首先要知道一个函数的作用以及具体的参数:
int cvCreateTrackbar(//创建滑动条的函数
const char* trackbar_name, //滑动条的名称
const char* window_name, //窗口的名称
int* value, //当滑动条被拖到时,OpenCV会自动将当前位置所代表的值传给指针指向的整数
int count, //滑动条所能达到的最大值(所有的帧数)
CvTrackbarCallback on_change //回调函数,每次滑块位置改变时,调用的函数的指针,并且函数应该声明为void Foo(int),如果没有回调函数,则设置为NULL);
两个得到或者修改CvCapture对象的各种属性的函数(如果要知道所有的参数的话,可以参考:OpenCV参考手册之CvCapture结构体):
cvSetCaptureProperty()
cvGetCaptureProperty()
我们这里用到的是修改当前的帧数的位置,以及得到当前视频信息的所有帧数,我们知道这三个函数信息,以及2-2的视频播放设置,我们就可以很容易理解下面给出的程序了
#include
#include
#include
#include
using namespace cv;
int g_slider_position = 0; //滚动条位置全局变量
CvCapture* g_capture = NULL; //确定要读入AVI文件的指针
void onTrackbarSlide(int pos)
{
cvSetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES, pos); //以帧数设置读入位置
}//回调函数,当拖时调用这个函数
int main(int argc, char** argv)
{
cvNamedWindow("Example3", CV_WINDOW_AUTOSIZE); //创建窗口
g_capture = cvCreateFileCapture("视频位置");
int frames = (int)cvGetCaptureProperty(g_capture, CV_CAP_PROP_FRAME_COUNT); //获取总帧数以设定滚动条
if (frames != 0)
{
cvCreateTrackbar("Position", "Example3", &g_slider_position, frames, onTrackbarSlide); //创建滚动条
}
IplImage* frame;
while (1)
{
frame = cvQueryFrame(g_capture);
if (!frame) break;
cvShowImage("Example3", frame);
g_slider_position ++;
cvCreateTrackbar("Position", "Example3", &g_slider_position, frames, onTrackbarSlide);//重新更新进度条
char c = cvWaitKey(32);
if (c == 27) break;
}
cvReleaseCapture(&g_capture);
cvDestroyWindow("Example3");
return(0);
}
实现效果是:进度条在视频的上方,很诡异........
栗子2-4
一个简单的变换,要求我们对图像进行平滑处理,我们这里面会涉及到的函数包括:
cvCreateImage函数,具体参见:https://blog.csdn.net/lixam/article/details/7596074
IplImage* cvCreateImage( CvSize size, int depth, int channels );
//size:图像大小
//depth:图像元素的位深度
//channels:每个元素(像素)通道号
cvGetSize()函数:函数返回图像的长宽
cvsmooth()函数:函数平滑滤波 详见:https://www.cnblogs.com/yangxuebing/p/6896260.html
#include
#include
using namespace std;
void example2_4(IplImage* image)
{
cvNamedWindow("Example4-in", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example4-out", CV_WINDOW_AUTOSIZE);
cvShowImage("Example4-in", image);
IplImage* out = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 3); //(图像大小,每个像素点数据类型 ,通道数)
cvSmooth(image, out, CV_GAUSSIAN, 3, 3); //对3*3的区域进行高斯平滑处理
cvShowImage("Example4-out", out);
cvReleaseImage(&out);
cvReleaseImage(&image);
cvWaitKey(0);
cvDestroyWindow("Example4-in");
cvDestroyWindow("Example4-out");
}
int main(int argc, char** argv)
{
IplImage *img = cvLoadImage("图片地址");
example2_4(img);
}
实现效果:
使用opencv3的语法:
#include
#include
#include
using namespace cv;
int main()
{
namedWindow("原图",0);
namedWindow("图像腐蚀",0);
Mat img = imread("图片位置");
imshow("原图", img);
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));(返回指定形状和尺寸的结构元素)
Mat dstImage;
erode(img, dstImage, element); (进行腐蚀操作)
imshow("图像腐蚀", dstImage);
waitKey(0);
destroyAllWindows();
return 0;
}
栗子2-5
实现图片的缩放,那么对应的函数就是:cvPyrUp,cvPyrDown ,他们的类型是类似的,我们需要串的参数也是相同的,但是我们在cvCreateImage上我们所创建的图像大小就不能相同了,在缩小最前会有一个断言,就是只有在长宽像素都是偶数的情况下我们才能进行缩小操作
#include
#include
using namespace std;
IplImage* doPyrDomn(IplImage *in,int filter = CV_GAUSSIAN_5x5)
{
assert(in->width % 2 == 0 && in->height % 2 == 0);
IplImage *out = cvCreateImage(
cvSize(in->width / 2, in->height / 2),
in->depth,
in->nChannels
);
cvPyrDown(in, out);
return out;
}
IplImage* doPyrUp(IplImage *in)
{
IplImage *out = cvCreateImage(
cvSize(in->width * 2, in->height * 2),
in->depth,
in->nChannels
);
cvPyrUp(in, out);
return out;
}
int main(int argc, char** argv)
{
IplImage *img = cvLoadImage("图片位置");
cvNamedWindow("Example5 - in",CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example5 - out1", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example5 - out2", CV_WINDOW_AUTOSIZE);
cvShowImage("Example5 - in", img);
IplImage *out = doPyrDomn(img);
cvShowImage("Example5 - out1", out);
out = doPyrUp(img);
cvShowImage("Example5 - out2", out);
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&out);
cvDestroyAllWindows();
}
栗子2-6
要求进行Canny边界检测,那么Canny算法在opencv中的函数是:
Canny(const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size = 3)
具体参照:https://blog.csdn.net/hitwengqi/article/details/6877864
Canny函数要求输入的图像必须是单通道的图片,那么我们在函数cvLoadImage()的第二个参数就有是否加载颜色的表示
-1:默认读取图像原通道数
0:强制转换为灰度图片
1:读取彩色图
除了这种方法还有利用cvCVtColor()函数:
cvCvtColor(img, img_, CV_BGR2GRAY);//将img强制转换为img_灰度图片
#include
#include
using namespace std;
IplImage * doCanny(IplImage* in, double lowThresh, double highThresh, double aperture)
{
if (in->nChannels != 1)
return 0;
IplImage *out = cvCreateImage(
cvGetSize(in),
IPL_DEPTH_8U,
1
);
cvCanny(in, out, lowThresh, highThresh, aperture);
return out;
}
int main(int argc, char** argv)
{
IplImage *img = cvLoadImage("图片位置",-1);
IplImage *out = doCanny(img, 50, 150, 3);
cvNamedWindow("Example5 - in",0);
cvNamedWindow("Example5 - out",0);
cvShowImage("Example5 - in",img);
cvShowImage("Example5 - out", out);
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&out);
cvDestroyAllWindows();
}
栗子2-7
因为栗子为上面两个的结合,就不在进行叙述
#include
#include
using namespace std;
IplImage * doCanny(IplImage* in, double lowThresh, double highThresh, double aperture)
{
if (in->nChannels != 1)
return 0;
IplImage *out = cvCreateImage(
cvGetSize(in),
IPL_DEPTH_8U,
1
);
cvCanny(in, out, lowThresh, highThresh, aperture);
return out;
}
IplImage *doPyrDomn(IplImage *in)
{
assert(in->width % 2 == 0 && in->height % 2 == 0);
IplImage *out = cvCreateImage(
cvSize(in->width / 2, in->height / 2),
in->depth,
in->nChannels
);
cvPyrDown(in, out);
return out;
}
int main(int argc, char** argv)
{
cvNamedWindow("Example7", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example7-G", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example7-S", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example7-SG", CV_WINDOW_AUTOSIZE);
IplImage *img = cvLoadImage("C:\\Users\\dell\\Desktop\\乱七八糟\\图片\\3.jpg",-1);
IplImage *img_ = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,img->nChannels);
cvShowImage("Example7", img); //原图
img_ = doPyrDomn(img);
img = doPyrDomn(img_);//
cvShowImage("Example7-S",img);//缩小两倍
IplImage *Gimg = cvCreateImage(cvGetSize(img), img->depth, 1);
cvCvtColor(img, Gimg, CV_BGR2GRAY);
cvShowImage("Example7-G", Gimg);//灰度图
IplImage *out = doCanny(Gimg, 50, 150, 3);
cvShowImage("Example7-SG", out);//Canny边界检测
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&img_);
cvReleaseImage(&out);
cvReleaseImage(&Gimg);
cvDestroyAllWindows();
}
栗子2-8
从摄像机读入数据,怎么更改设置我的摄像头都是只是有一个灰框,无法成像,所以换做成opencv3的语法成功实现
《学习Opencv》