OpenCV - C++实战(02) — 图片点击与绘图

目录

第2章  图片点击与绘图

2.1 图像点击

2.1.1 在图上点击

2.2 在图像上绘图

2.2.1 在图像上绘制基本图像

2.2.2 在图像上写入文本

2.2.3 在图像上插入logo

2.3 完整代码


 Github代码地址:https://github.com/Qinong/OpenCV.git

第2章  图片点击与绘图

2.1 图像点击

2.1.1 在图上点击

        highgui 模块中有使程序对鼠标或键盘事件做出响应、在图像上绘制形状或写人文本的函数。
可以让鼠标在置于图像窗口上时运行特定的指令。要实现这个功能,需定义一个合适的回调函数。回调函数不会被显式地调用,但是会在响应特定事件(这里是指有关鼠标与图像窗口交互的事件)的时候被程序调用。为了能被程序识别,回调函数需要具有特定的签名,并且必须注册。对于鼠标事件处理两数,回调函数必须具有这种签名:

void onMouse( int event, int x, int y, int flags, void* param)

                event:表示触发回调的数的鼠标事件的类型。

                x,y:两个参数是事件发生时鼠标的位置,用像素坐标表示。

                flags:表示事件发生时按下了鼠标的哪个键。

                param:指向任意对象的指针,作为附加的参数发送给函数。

        你可用下面的方法 在程序中注册回调函数:

void cv::setMouseCallback(const String &winname,cv::MouseCallback onMouse,void *userdata=(void*)0)
  • winname:窗口名称
  • onMouse:鼠标事件的回调函数
  • userdata:传递给回调函数的可选参数
  • event:所发生的事件

                EVENT_MOUSEMOVE    0    鼠标移动

                EVENT_LBUTTONDOWN  1  按下鼠标左键

                EVENT_RBUTTONDOWN  2  按下鼠标右键

                EVENT_MBUTTONDOWN 3  按下鼠标中键

                EVENT_LBUTTONUP 4  放开鼠标左键

                EVENT_RBUTTONUP 5  放开鼠标右键

                EVENT_MBUTTONUP  6 放开鼠标中键

                EVENT_LBUTTONDBLCLK 7  鼠标左键双击

                EVENT_RBUTTONDBLCLK  8 鼠标右键双击

                EVENT_MBUTTONDBLCLK 9  鼠标中键双击

  • x,y:鼠标所在图像的坐标
  • flags:代表拖拽事件

                EVENT_FLAG_LBUTTON  1 按住左键拖拽

                EVENT_FLAG_RBUTTON 2  按住右键拖拽

                EVENT_FLAG_MBUTTON 4  按住中键拖拽

                EVENT_FLAG_CTRLKEY 8  按住ctrl键拖拽

                EVENT_FLAG_SHIFTKEY  16 按住shift键拖拽

                EVENT_FLAG_ALTKEY 32  按住alt键拖拽

  • param: 自己定义的onMouse事件的ID

 (1)显示鼠标点击点的像素值

void onMouse( int event, int x, int y, int flags, void* param)	{
	cv::Mat *im= reinterpret_cast<cv::Mat*>(param);
    switch (event) {    // 调度事件
		case cv::EVENT_LBUTTONDOWN: // 鼠标左键按下的事件
			// 显示鼠标点按下的像素值(x,y)
			std::cout << "at (" << x << "," << y << ") value is: " 
				      << static_cast<int>(im->at<uchar>(cv::Point(x,y))) << std::endl;
			break;
	}
}

2.2 在图像上绘图

2.2.1 在图像上绘制基本图像

        OpenCV 提供了几个用于在图像上绘制形状的函数,基本的形状绘制函数有circle、ellipse、line 和 rectangle。

void cv::circle (InputOutputArray img,     // 图像
                 Point center,         // 圆心点
                 int radius,           // 半径
                 const Scalar &color,    // 颜色
                 int thickness=1,       // 线条粗细
                 int lineType=LINE_8,     // 线条类型
                 int shift=0)            // 中心坐标和半径值中的小数位数

(1)在图上画圆

cv::Mat image2 = image1.clone();
cv::circle(image2,              // 目标图像
		   cv::Point(1500,2000), // 中心点坐标
		   500,                 // 半径
		   0,                  // 颜色
		   50);                 // 厚度
cv::namedWindow("Image2",0);
cv::imshow("Image2", image2); 
cv::waitKey(0); 

2.2.2 在图像上写入文本

        在OpenCV 的方法和函数中,你也可以在图像上写人文本,方法如下所示: 

void cv::putText(cv::Mat& img, // 待绘制的图像
	             const string& text, // 待绘制的文字
	             cv::Point origin, // 文本框的左下角
	             int fontFace, // 字体 (如cv::FONT_HERSHEY_PLAIN)
		         double fontScale, // 尺寸因子,值越大文字越大
		         cv::Scalar color, // 线条的颜色(RGB)
		         int thickness = 1, // 线条宽度
		         int lineType = 8, // 线型(4邻域或8邻域,默认8邻域)
		         bool bottomLeftOrigin = false // 指定的点为插入文字的位置(true=文字的左上角位置,false=文字的左下角位置)
                );

 (1)在图像上写入文本

cv::Mat image3 = image1.clone();
cv::putText(image3,                   // destination image
		    "This is a Audi.",        // text
		    cv::Point(1000,2500),       // text position
		    cv::FONT_HERSHEY_PLAIN,  // font type
			20.0,                     // font scale
			255,                     // text color (here white)
			20);                      // text thickness
cv::namedWindow("Image3",0);
cv::imshow("Image3", image3); 
cv::waitKey(0); 

        假设我们要把一 个小图像复制到一个大图像上。例如要把下面的logo插人到测试图像中。
为了实现这个功能,可以定义一个兴趣区域 (Region Of Interest, ROI),在此处进行复制操作,这个ROI的位置将决定标志的插人位置。

         第一步是定义 ROI。定义后,就可以把 ROI当作一个普通的cv::Mat 实例进行操作。接着,可以用下面的方法插人标志:

// cv::Rect矩形类参数设置
cv::Rect(int x, int y,         // 左上角坐标
         int width, int height);    // 矩形的宽和高 

        cv:Range类型用于指元连续的整数序列,包合两个元素start和end,通过cv:Range (int start, int end)进行初始化。生成结果包括起始值,但不含终值。

(1)方法1:图片插入logo

// 方法1:图片插入logo
cv::Mat image4 = image1.clone(); 
cv::Mat logo=  cv::imread("Audi_logo.jpeg"); 
// 在图像的右下角定义一个ROI
cv::Mat imageROI(image4, 
		         cv::Rect(image4.cols-logo.cols, // ROI坐标
                          image4.rows-logo.rows,
		                  logo.cols,logo.rows));// ROI大小
// 插入logo
logo.copyTo(imageROI);
cv::namedWindow("Image4",0); 
cv::imshow("Image4", image4); 
cv::waitKey(0);

(2)方法2:图片插入logo

// 方法2:图片插入logo
cv::Mat image5 = image1.clone(); 
cv::Mat logo1=  cv::imread("Audi_logo.jpeg",cv::IMREAD_GRAYSCALE); 
// ROI用cv::Range描述
imageROI= image5(cv::Range(image5.rows-logo.rows,image5.rows), 
                 cv::Range(image5.cols-logo.cols,image5.cols));

// 用logo作为掩码(必须是灰度图像)
cv::Mat mask(logo1);
// 插入logo,只负责掩码不为0的位置
logo.copyTo(imageROI,mask);
cv::namedWindow("Image5",0);
cv::imshow("Image5", image5); 
cv::waitKey(0);

        运行上述代码后,你将得到下面的图像。

 

2.3 完整代码

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>


void onMouse( int event, int x, int y, int flags, void* param)	{
	cv::Mat *im= reinterpret_cast<cv::Mat*>(param);
    switch (event) {    // 调度事件
		case cv::EVENT_LBUTTONDOWN: // 鼠标左键按下的事件
			// 显示鼠标点按下的像素值(x,y)
			std::cout << "at (" << x << "," << y << ") value is: " 
				      << static_cast<int>(im->at<uchar>(cv::Point(x,y))) << std::endl;
			break;
	}
}

int main() {
	// code1
    // 显示鼠标点击点的像素值
    cv::Mat image1 = cv::imread("Audi_RS7.jpg");
    if (image1.empty()) { 
		std::cout << "Error reading image..." << std::endl;
		return 0;
	}
    cv::namedWindow("Image1",0); 
	cv::imshow("Image1", image1); // show the image
	cv::waitKey(0); // 0 to indefinitely wait for a key pressed
	cv::setMouseCallback("Image1", onMouse, reinterpret_cast<void*>(&image1));
    
    // code2
    // 在图上画圆
    cv::Mat image2 = image1.clone();
 	cv::circle(image2,              // 目标图像
		       cv::Point(1500,2000), // 中心点坐标
			   500,                 // 半径
			   0,                  // 颜色
			   50);                 // 厚度
    cv::namedWindow("Image2",0);
	cv::imshow("Image2", image2); 
	cv::waitKey(0); 
	 
    // code3
    // 在图上写入文本
    cv::Mat image3 = image1.clone();
	cv::putText(image3,                   // destination image
		        "This is a Audi.",        // text
				cv::Point(1000,2500),       // text position
				cv::FONT_HERSHEY_PLAIN,  // font type
				20.0,                     // font scale
				255,                     // text color (here white)
				20);                      // text thickness
    cv::namedWindow("Image3",0);
	cv::imshow("Image3", image3); 
	cv::waitKey(0);   

    // code4
    // 方法1:图片插入logo
	cv::Mat image4 = image1.clone(); 
	cv::Mat logo=  cv::imread("Audi_logo.jpeg"); 
	// 在图像的右下角定义一个ROI
	cv::Mat imageROI(image4, 
		          cv::Rect(image4.cols-logo.cols, // ROI坐标
                           image4.rows-logo.rows,
		                   logo.cols,logo.rows));// ROI大小
	// 插入logo
	logo.copyTo(imageROI);
	cv::namedWindow("Image4",0); 
	cv::imshow("Image4", image4); 
	cv::waitKey(0);


    // code5
    // 方法2:图片插入logo
	cv::Mat image5 = image1.clone(); 
    cv::Mat logo1=  cv::imread("Audi_logo.jpeg",cv::IMREAD_GRAYSCALE); 
	// ROI用cv::Range描述
    imageROI= image5(cv::Range(image5.rows-logo.rows,image5.rows), 
                    cv::Range(image5.cols-logo.cols,image5.cols));

    // 用logo作为掩码(必须是灰度图像)
    cv::Mat mask(logo1);
	// 插入logo,只负责掩码不为0的位置
	logo.copyTo(imageROI,mask);
    cv::namedWindow("Image5",0);
	cv::imshow("Image5", image5); 
	cv::waitKey(0);
    
	return 0;
}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenCV-Python是一个基于Python的计算机视觉库,它提供了许多用于图像处理和计算机视觉任务的函数和工具。在使用OpenCV-Python进行实战时,首先需要安装配套使用的opencv-contrib-python库,最好保持版本一致,可以使用以下命令进行安装:pip install opencv-contrib-python。 在实战中,可以通过OpenCV-Python进行图像的基本操作。例如,可以使用OpenCV-Python读取图像文件,可以使用cv2.imread函数来读取图像,如下所示:img = cv2.imread('image.jpg')。 另外,OpenCV-Python还可以用于处理视频文件。可以使用cv2.VideoCapture函数来打开视频文件,然后使用循环逐帧读取视频帧,并对每一帧进行处理。例如,可以将每一帧转换为灰度图像,并使用cv2.imshow函数显示处理结果。可以使用以下代码来实现视频文件的处理: ``` vc = cv2.VideoCapture('video.mp4') # 打开视频文件 while vc.isOpened(): ret, frame = vc.read() # 读取视频帧 if frame is None: break if ret == True: gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 将帧转换为灰度图像 cv2.imshow("result", gray) # 显示灰度图像 if cv2.waitKey(10) & 0xFF == 27: # 按下ESC键退出循环 break vc.release() cv2.destroyAllWindows() ``` 此外,OpenCV-Python还可以进行图像数据的截取,可以使用切片操作来截取图像的特定区域。例如,可以使用以下代码来截取图像的一部分数据:cat = img[0:50, 0:200],其中[0:50, 0:200]表示截取图像的高度为50像素,宽度为200像素的区域。 还可以使用OpenCV-Python提取图像的颜色通道。例如,可以使用以下代码来提取图像的蓝色通道:blue_channel = img[:, :, 0],其中[:, :, 0]表示提取图像的第0个通道,即蓝色通道。同样的方法可以用于提取其他颜色通道。 综上所述,OpenCV-Python提供了丰富的函数和工具,可以用于图像处理和计算机视觉任务的实战。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [基于python的opencv的学习和实战](https://blog.csdn.net/weixin_44001965/article/details/112862177)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatgptT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

几度春风里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值