《学习Opencv》_第二章Opencv入门

因为要参加老师的一个小项目,所以今天开始学习关于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 <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/core/core.hpp>  
#include <highgui.h>
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 <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/core/core.hpp>  
#include <highgui.h>
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()函数 来对帧率进行更好地判定

扫描二维码关注公众号,回复: 269191 查看本文章

栗子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 <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/core/core.hpp>  
#include <highgui.h>
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 <cv.h>
#include <highgui.h>

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 <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>  

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 <cv.h>
#include <highgui.h>

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 <cv.h>
#include <highgui.h>

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 <cv.h>
#include <highgui.h>

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》




猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/80213037