【OpenCV3学习笔记四】OpneCV快速上手

本文详细介绍使用OpenCV进行图像处理的各种技巧,包括图像显示、写图、腐蚀操作、显示视频、Canny边缘检测等核心功能,并展示了如何通过鼠标操作、滑动条等方式提升交互性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 


1、图像显示

 

/**********************************************/
// Mat imread(const string& filename ,int flag=1);
// 第一个参数,const string&类型的filename,填我们需要载入的图片路径名。
// Windows位图 - *.bmp, *.dib
// *.jpeg, *.jpg, *.jpe *.jp2  *.png - *.pbm, *.pgm, *.ppm  *.sr, *.ras  *.tiff, *.tif
// 第二个参数,int类型的flags,为载入标识,它指定一个加载图像的颜色类型。
// 可以看到它自带缺省值1.所以有时候这个参数在调用时我们可以忽略,如果忽略表示三通道的彩色图像。
// enum
// {
//	/* 8bit, color or not */
//	CV_LOAD_IMAGE_UNCHANGED = -1,
//	/* 8bit, gray */
//	CV_LOAD_IMAGE_GRAYSCALE = 0,
//	/* ?, color */
//	CV_LOAD_IMAGE_COLOR = 1,
//	/* any depth, ? */
//	CV_LOAD_IMAGE_ANYDEPTH = 2,
//	/* ?, any color */
//	CV_LOAD_IMAGE_ANYCOLOR = 4
// };

//CV_LOAD_IMAGE_UNCHANGED,这个标识在新版本中被废置了,忽略。
//CV_LOAD_IMAGE_ANYDEPTH - 如果取这个标识的话,若载入的图像的深度为16位或者32位,就返回对应深度的图像,否则,就转换为8位图像再返回。
//CV_LOAD_IMAGE_COLOR - 如果取这个标识的话,总是转换图像到彩色一体
//CV_LOAD_IMAGE_GRAYSCALE - 如果取这个标识的话,始终将图像转换成灰度1
//如果输入有冲突的标志,将采用较小的数字值。比如CV_LOAD_IMAGE_COLOR | CV_LOAD_IMAGE_ANYCOLOR 将载入3通道图。
//如果想要载入最真实的图像,选择CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR。

/**********************************************/
void main()  //读图
{
	// TODO:  在此添加控件通知处理程序代码

	Mat myMat = imread("1.jpg");
	Mat image0 = imread("1.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//载入最真实的图像
	Mat image1 = imread("1.jpg", 0);//载入灰度图
	Mat image2 = imread("1.jpg", 199);//载入3通道的彩色图像
	Mat logo = imread("1.jpg");//载入3通道的彩色图像

	imshow("原图1", myMat);
	waitKey(0);
	imshow("原图2", image0);
	waitKey(0);
	imshow("原图3", image1);
	waitKey(0);
	imshow("原图4", image2);
	waitKey(0);
	imshow("原图5", logo);
	waitKey(0);
}

 

 

2、写图

 

 

// bool imwrite(const string& filename,InputArray img, const vector<int>& params=vector<int>() );
// 第一个参数,const string&类型的filename,填需要写入的文件名就行了,带上后缀,比如,“123.jpg”这样。
// 第二个参数,InputArray类型的img,一般填一个Mat类型的图像数据就行了。
// 第三个参数,const vector<int>&类型的params,表示为特定格式保存的参数编码,它有默认值vector<int>(),
// 所以一般情况下不需要填写。而如果要填写的话,有下面这些需要了解的地方:
// 对于JPEG格式的图片,这个参数表示从0到100的图片质量(CV_IMWRITE_JPEG_QUALITY),默认值是95.
// 对于PNG格式的图片,这个参数表示压缩级别(CV_IMWRITE_PNG_COMPRESSION)从0到9。
// 较高的值意味着更小的尺寸和更长的压缩时间,而默认值是3。
//
// void namedWindow(const string& winname,int flags=WINDOW_AUTOSIZE );  顾名思义,namedWindow函数,用于创建一个窗口。
//第一个参数,const string&型的name,即填被用作窗口的标识符的窗口名称。
//第二个参数,int 类型的flags ,窗口的标识,可以填如下的值:
//WINDOW_NORMAL设置了这个值,用户便可以改变窗口的大小(没有限制)
//WINDOW_AUTOSIZE如果设置了这个值,窗口大小会自动调整以适应所显示的图像,并且不能手动改变窗口大小。
//WINDOW_OPENGL 如果设置了这个值的话,窗口创建的时候便会支持OpenGL。

void OnBnClickedimwrite()
{
	// TODO:  在此添加控件通知处理程序代码
	Mat mat(480, 640, CV_8UC4);

	for (int i = 0; i < mat.rows; ++i) 
	{
		for (int j = 0; j < mat.cols; ++j) 
		{
			Vec4b&rgba = mat.at<Vec4b>(i, j);
			rgba[0] = UCHAR_MAX;
			rgba[1] = saturate_cast<uchar>((float(mat.cols - j)) / ((float)mat.cols) *UCHAR_MAX);
			rgba[2] = saturate_cast<uchar>((float(mat.rows - i)) / ((float)mat.rows) *UCHAR_MAX);
			rgba[3] = saturate_cast<uchar>(0.5 * (rgba[1] + rgba[2]));
		}
	}

	vector<int>compression_params;
	compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
	compression_params.push_back(9);

	try{
		imwrite("透明Alpha值图.png", mat, compression_params);
	}
	catch (runtime_error& ex) {
		fprintf(stderr, "图像转换成PNG格式发生错误:%s\n", ex.what());		
	}
		
}

 

3、图像腐蚀

void CTestCvDlg::OnBnClickedErode()
{
	// TODO:  在此添加控件通知处理程序代码

	//载入原图  
	Mat srcImage = imread("1.jpg");
	//显示原图
	imshow("【原图】腐蚀操作", srcImage);
	//进行腐蚀操作 
	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
	Mat dstImage;
	erode(srcImage, dstImage, element);
	//显示效果图 
	imshow("【效果图】腐蚀操作", dstImage);
	waitKey(0);
}

4、显示视频

int main()
{	
    VideoCapture capture(0);//opencv调用摄像头读取视频

    //【2】循环显示每一帧
    while (1)
    {
        Mat frame;//定义一个Mat变量,用于存储每一帧的图像
	capture >> frame;  //读取当前帧

	imshow("读取视频", frame);
	if (waitKey(30) == 27)//按下Esc键退出读取视频操作
		break;

    }
    return 0;
}




5、Canny边缘检测

 

void CTestCvDlg::OnBnClickedCanny()
{
	// TODO:  在此添加控件通知处理程序代码
	//【0】载入原始图  
	Mat srcImage = imread("1.jpg");  //工程目录下应该有一张名为1.jpg的素材图
	imshow("【原始图】Canny边缘检测", srcImage); 	//显示原始图 
	Mat dstImage, edge, grayImage;	//参数定义

	//【1】创建与src同类型和大小的矩阵(dst)
	dstImage.create(srcImage.size(), srcImage.type());

	//【2】将原图像转换为灰度图像
	//此句代码的OpenCV2版为:
	//cvtColor( srcImage, grayImage, CV_BGR2GRAY );
	//此句代码的OpenCV3版为:
	cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);

	//【3】先用使用 3x3内核来降噪
	blur(grayImage, edge, Size(3, 3));

	//【4】运行Canny算子
	Canny(edge, edge, 3, 9, 3);

	//【5】将g_dstImage内的所有元素设置为0
	dstImage = Scalar::all(0);

	//【6】使用Canny算子输出的边缘图g_cannyDetectedEdges作为掩码,来将原图g_srcImage拷到目标图g_dstImage中
	srcImage.copyTo(dstImage, edge);

	//【7】显示效果图 
	imshow("【效果图】Canny边缘检测", edge);

	waitKey(0);
}

6、鼠标操作

 

/****************************************/
//void::SetMouseCallback为鼠标回调函数
//void setMouseCallback(conststring& winname, MouseCallback onMouse, void* userdata= 0)
//第一个参数 const string& 类型的winname,窗口的名字
//第二个参数 MouseCallback 类型的onMouse, 指定的窗口里每次鼠标事件发生的时候,被调用的函数指针
//第三个参数 void* 类型的userdata,用户定义的传递到回调函数的参数,有默认值0.
/****************************************/
void FunctionAnalysis::OnBnClickedMouse()  //鼠标操作
{
	// TODO:  在此添加控件通知处理程序代码
	//【1】参数准备
	g_rectangle = Rect(-1, -1, 0, 0);
	Mat srcImage(600, 800, CV_8UC3), tempImage;
	srcImage.copyTo(tempImage);
	g_rectangle = Rect(-1, -1, 0, 0);
	srcImage = Scalar::all(0);

	//【2】设置鼠标操作回调函数
	namedWindow(WINIDOW_NAME1);
	setMouseCallback(WINIDOW_NAME1, on_MouseHandle, (void*)&srcImage);

	//【3】程序主循环,当进行绘制的标示符为真时,进行绘制
	while (1)
	{
		srcImage.copyTo(tempImage);//拷贝源图到临时变量
		if (g_bDrawingBox)
		{
			DrawRectangle(tempImage, g_rectangle);////当进行绘制的标识符为真,则进行绘制
		}
		imshow(WINIDOW_NAME1, tempImage);
		if (waitKey(10) == 27)
		{
			break; //按下ESC键,程序退出
		}
	}
}

7、滑动条


//Mat img;
//int threshval = 160;			//轨迹条滑块对应的值,给初值160
//-----------------------------【on_trackbar( )函数】------------------------------------
//	描述:轨迹条的回调函数
//-----------------------------------------------------------------------------------------------
static void on_Trackbar(int, void*)
{			
	//求出当前alpha值相对于最大值的比例
	g_dAlphaValue = (double)g_nAlphaValueSlider / g_nMaxAlphaValue;
	//则beta值为1减去alpha值
	g_dBetaValue = (1.0 - g_dAlphaValue);

	//根据alpha和beta值进行线性混合
	addWeighted(g_srcImage1, g_dAlphaValue, g_srcImage2, g_dBetaValue, 0.0, g_dstImage);

	//显示效果图
	imshow(WINDOW_NAME, g_dstImage);

}

/***********************************************/
//创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上.
//0、int createTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange = 0, void* userdata = 0);
//1、const string&类型的trackbarname,表示轨迹条的名字,用来代表我们创建的轨迹条。
//2、const string&类型的winname,填窗口的名字,表示这个轨迹条会依附到哪个窗口上,即对应namedWindow()创建窗口时填的某一个窗口名。
//3、int* 类型的value,一个指向整型的指针,表示滑块的位置。并且在创建时,滑块的初始位置就是该变量当前的值。
//4、int类型的count,表示滑块可以达到的最大位置的值。PS:滑块最小的位置的值始终为0。
//5、TrackbarCallback类型的onChange,首先注意他有默认值0。这是一个指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。
//6、void*类型的userdata,他也有默认值0。这个参数是用户传给回调函数的数据,用来处理轨迹条事件。
/***********************************************/
void OnBnClickedcreatetrackbar()
{
	// TODO:  在此添加控件通知处理程序代码

	//加载图像 (两图像的尺寸需相同)
	g_srcImage1 = imread("1.jpg");
	if (!g_srcImage1.data) 
	{ 
		printf("读取第一幅图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); 		
	}

	g_srcImage2 = imread("1.jpg");
	if (!g_srcImage2.data)
	{
		printf("读取第一幅图片错误,请确定目录下是否有imread函数指定图片存在~! \n");
	}
	
	//设置滑动条初值为70
	g_nAlphaValueSlider = 70;

	//创建窗体
	namedWindow(WINDOW_NAME, 1);

	//在创建的窗体中创建一个滑动条控件
	char TrackbarName[50];
	sprintf_s(TrackbarName, "透明值 %d", g_nMaxAlphaValue);

	createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue, on_Trackbar);

	//结果在回调函数中显示
	on_Trackbar(g_nAlphaValueSlider, 0);

	//按任意键退出
	waitKey(0);	

}

 

8、图像的载入、显示和输出到文件

void CTestCvDlg::OnBnClickedimreadwrite()
{
	// TODO:  在此添加控件通知处理程序代码
	//------【一、图像的载入和显示】--------------
	Mat girl = imread("girl.png");  //载入图像到Mat
	namedWindow("1动漫图");  //创建一个名为“1动漫图”的窗口
	imshow("1动漫图",girl);  //显示名为“1动漫图”的窗口
	waitKey();
	//------【二、初级图像混合】------------------
	//载入图片
	Mat image = imread("dota.png",199);
	Mat logo = imread("logo.png");
	//载入先后显示
	namedWindow("2原图");
	imshow("2原图",image);

	namedWindow("3原图");
	imshow("3原图",logo);

	//定义一个Mat类型,用于存放,图像的ROI
	Mat imageROI;
	//方法一
	//imageROI = image(Rect(800, 350, logo.cols, logo.rows));
	//方法二
	imageROI=image(Range(350,350+logo.rows),Range(800,800+logo.cols));//有bug

	//将logo加到原图上
	addWeighted(imageROI, 0.5, logo, 0.3, 0., imageROI);

	//显示结果
	namedWindow("3原图+logo图");
	imshow("3原图+logo图", image);

	//--------------【三、图像的输出】---------------------
	//输出一张jpg图片到工程目录下
	imwrite("dota.jpg", image);
	waitKey(0);
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值