IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> opencv C艹:几何图绘制,ROI,图像金字塔,滚动条,鼠标响应 -> 正文阅读

[人工智能]opencv C艹:几何图绘制,ROI,图像金字塔,滚动条,鼠标响应

图像上绘制几何图形

绘制圆形

void cv::circle	(	InputOutputArray 	img,
					Point 	center,  // 圆心
					int 	radius,  // 半径
					const Scalar & 	color,
					int 	thickness = 1, // 边界宽度 负数实心
					int 	lineType = LINE_8, // 边界类型
					int 	shift = 0  // 中心坐标和半径数值的小数位数
)	
void cv::line	(	InputOutputArray 	img,
					Point 	pt1,  // 起点
					Point 	pt2,   // 终点
					const Scalar & 	color,
					int 	thickness = 1,
					int 	lineType = LINE_8,
					int 	shift = 0  // 点坐标中的小数位数。
)	

void cv::ellipse	(	InputOutputArray 	img,
						Point 	center, // 椭圆中心
						Size 	axes,  // 主轴的一半
						double 	angle,  // 旋转角度
						double 	startAngle, // 椭圆弧的起始角度,度
						double 	endAngle, // 终止角度
						const Scalar & 	color,
						int 	thickness = 1,
						int 	lineType = LINE_8,
						int 	shift = 0 
)	

// 输出椭圆边界的像素坐标,不会绘制椭圆
void cv::ellipse2Poly	(	Point 	center,
							Size 	axes,
							int 	angle,
							int 	arcStart,
							int 	arcEnd,
							int 	delta,  
							std::vector< Point > & 	pts //存储椭圆边缘的坐标点
)	
// 绘制矩形
void cv::rectangle	(	InputOutputArray 	img,
						Point 	pt1,  // 对角点
						Point 	pt2,
						const Scalar & 	color,
						int 	thickness = 1,
						int 	lineType = LINE_8,
						int 	shift = 0 
)	

void cv::rectangle	(	InputOutputArray 	img,
						Rect 	rec,   // 左上顶点坐标和长宽
						const Scalar & 	color,
						int 	thickness = 1,
						int 	lineType = LINE_8,
						int 	shift = 0 
)	
Rect变量与Point一样表示矩形的含义,表示的时矩形的左上角坐标和 w,h。Rect2i,Rect2d,Rect2f

// 多边形
void cv::fillPoly	(	InputOutputArray 	img,
						const Point ** 	pts, // 多边形顶点数组,可以存放多个多边形的顶点坐标的数组
						const int * 	npts, // 每个多边形顶点数组中顶点的个数,数组
						int 	ncontours, // 多边形的个数
						const Scalar & 	color,
						int 	lineType = LINE_8,
						int 	shift = 0,
						Point 	offset = Point() 
)	


void cv::putText	(	InputOutputArray 	img,
						const String & 	text, 
						Point 	org,  // 左上角坐标
						int 	fontFace,  // 字体
						double 	fontScale, // 字体大小
						Scalar 	color,  
						int 	thickness = 1,
						int 	lineType = LINE_8,
						bool 	bottomLeftOrigin = false  // 图像原点位置,默认左上,true改为左下
)	

在这里插入图片描述

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat img = Mat::zeros(Size(512, 512), CV_8UC3);  // 底图

	circle(img, Point(50, 50), 25, Scalar(255, 255, 255), -1);
	circle(img, Point(50, 50), 50, Scalar(124, 22, 79), 4);

	line(img, Point(100, 100), Point(200, 200), Scalar(33, 33, 33), 2, LINE_4, 0);
	ellipse(img, Point(300, 255), Size(100, 70), 0, 0, 100, Scalar(44, 44, 44), -1); // 逆时针
	ellipse(img, RotatedRect(Point2f(150, 100), Size2f(30, 20), 0), Scalar(0, 0, 255), 2);
	
	vector<Point> points;
	ellipse2Poly(Point(200, 400), Size(100, 70), 0, 0, 360, 2, points); // 近似个椭圆
	for (int i = 0; i < points.size() - 1; i++)
	{
		if (i == points.size() - 1)
		{
			line(img, points[0], points[1], Scalar(255, 255, 255), 2);
		}
	}
	rectangle(img, Point(50, 400), Point(100, 400), Scalar(125, 125, 125), -1);
	rectangle(img, Rect(400, 450, 60, 50), Scalar(0, 125, 125), 2);
	
	// 多边形
	Point pp[2][6];
	pp[0][0] = Point(72, 200);
	pp[0][1] = Point(142, 204);
	pp[0][2] = Point(226, 263);
	pp[0][3] = Point(172, 310);
	pp[0][4] = Point(117, 319);
	pp[0][5] = Point(15, 260);
	pp[1][0] = Point(359, 339);
	pp[1][1] = Point(447, 351);
	pp[1][2] = Point(504, 349);
	pp[1][3] = Point(484, 433);
	pp[1][4] = Point(418, 449);
	pp[1][5] = Point(354, 402);
	Point pp2[5];
	pp2[0] = Point(350, 83);
	pp2[1] = Point(463, 90);
	pp2[2] = Point(500, 171);
	pp2[3] = Point(421, 194);
	pp2[4] = Point(338, 141);
	const Point* pts[3] = { pp[0],pp[1],pp2 };  //pts变量的生成
	int npts[] = { 6,6,5 };
	fillPoly(img, pts, npts, 3, Scalar(125, 125, 125), 8);

	putText(img, "HHH", Point(100, 400), 2, 1, Scalar(255, 122, 144));
	imshow("", img);
	waitKey(0);
	return 0;
}

感兴趣区域

从原图中截取部分进行处理(ROI),可以使用Rect 进行标记位置,或Range标记。另外,对于图像的赋值和拷贝分为浅拷贝,深拷贝。浅拷贝就是建立一个能访问数据的变量,不能独立。= 赋值就是浅拷贝,慎用。深拷贝就是创建变量的同时分配新的地址用于存储数据。copyTo()实现深拷贝

void cv::Mat::copyTo	(	OutputArray 	m	)	const

void cv::Mat::copyTo	(	OutputArray 	m,
		InputArray 	mask   // 掩模矩阵 CV_8U类型,与原图尺寸相同,通道数不一定
)		const

当掩模矩阵中某一位置不为 0时,表示复制原图像中相同位置的元素到新的图像中否则便不复制.
void cv::copyTo	(	InputArray 	src,
	OutputArray 	dst,
	InputArray 	mask 
)	
	Mat img = imread("lena.png");
	Mat noobcv = imread("noobcv.jpg");
	Mat ROI1, ROI2, ROI2_copy, mask, img2, img_copy, img_copy2;
	resize(noobcv, mask, Size(200, 200));
	img2 = img;  //浅拷贝
				 //深拷贝的两种方式
	img.copyTo(img_copy2);
	copyTo(img, img_copy, img);
	
	//两种在图中截取ROI区域的方式
	Rect rect(206, 206, 200, 200);  //定义ROI区域
	ROI1 = img(rect);  //截图
	ROI2 = img(Range(300, 500), Range(300, 500));  //第二种截图方式
	img(Range(300, 500), Range(300, 500)).copyTo(ROI2_copy);  //深拷贝
	mask.copyTo(ROI1);  //在图像中加入部分图像
	imshow("加入noobcv后图像", img);
	imshow("ROI对ROI2的影响", ROI2);
	imshow("深拷贝的ROI2_copy", ROI2_copy);
	circle(img, Point(300, 300), 20, Scalar(0, 0, 255), -1);  //绘制一个圆形
	imshow("浅拷贝的img2", img2);
	imshow("深拷贝的img_copy", img_copy);
	imshow("深拷贝的img_copy2", img_copy2);
	imshow("画圆对ROI1的影响", ROI1);

图像金字塔

通过多个分辨率表示图像的一种有效简单的结构,金字塔就是分辨率逐渐降低的图像的集合。

  • 高斯金字塔
    构建金字塔是解决不确定性的一种常用方式,高斯金字塔就是通过下采样不断减小尺寸。尺寸缩小一半。该函数首先将原始图像与内核矩阵进行卷积,然后通过剔除偶数行和列来下采样,实现的功能与 resize() 一样,就是使用的内部算法不同。。

void cv::pyrDown	(	InputArray 	src,
						OutputArray 	dst,
						const Size & 	dstsize = Size(), // 可以指定尺寸,也可以直接默认
						int 	borderType = BORDER_DEFAULT 
)	


  • 拉普拉斯金字塔,高斯通过底层图像向上构建图像,拉普拉斯通过上层小尺寸图像向下构建大尺寸图像。具有预测残差的作用,需要和高斯金字塔联合使用。
    假设一个高斯金字塔,对其中某层图像首先通过下采样得到缩小一半的图像,然后对这幅图像进行上采样,恢复尺寸,再求高斯金字塔的该层和上采样后的差值图,这个差值图就是拉普拉斯金字塔的一层。
    pyrUp() 参数同上
int main()
{
	Mat img = imread("lena.png");
	vector<Mat> Gauss, Lap;
	int level = 3;     // 高斯金字塔下采样次数
	Gauss.push_back(img);
	for (int i = 0; i < level; i++)
	{
		Mat gauss;
		pyrDown(Gauss[i], gauss); // 构建高斯金字塔
		Gauss.push_back(gauss);
	}
	for (int i = Gauss.size() - 1; i > 0; i--)  
	{
		Mat lap, upGauss;
		if (i == Gauss.size() - 1)  // 第一层,就是最小的那一层
		{
			Mat down;
			pyrDown(Gauss[i], down); // 下采样,在上采样,得到差值
			pyrUp(down, upGauss);
			lap = Gauss[i] - upGauss;
			Lap.push_back(lap);
		}
		pyrUp(Gauss[i], upGauss);
		lap = Gauss[i - 1] - upGauss;
		Lap.push_back(lap);
	}
	for (int i = 0; i < Gauss.size(); i++)
	{
		string name = to_string(i);
		imshow("G" + name, Gauss[i]);
		imshow("L" + name, Lap[i]);
	}
	waitKey(0);
	return 0;

}

窗口交互操作

用于对流程的控制,比如修改一些参数啥的。

滑动条

动态调整某些数值。

int cv::createTrackbar	(	const String & 	trackbarname, // 滑动条名
							const String & 	winname,  // 窗口名
							int * 	value, // 指向整数的指针,值反应滑块的位置
							int 	count, // 滑块的最大值
							TrackbarCallback 	onChange = 0,
// 每次滑块更改位置时要调用的函数的指针,原型是 void Foo(int, void*) 轨迹栏位置,用户数据
							void * 	userdata = 0 // 传递给回调 函数的可选参数.
)	

该函数可以在窗口上方创建一个从0开始的整数滑动条,只能输出整数,小数就需要后续处理。第五个参数是每次滑块更改位置时调用的函数的指针,最后一个参数时传递给回掉函数的 void* 数据

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

// 为了能在被调函数中使用,设置为全局的
int value;
void callBack(int, void*);
Mat img1, img2;

int main()
{
	img1 = imread("lena.png");
	namedWindow("滑动条");
	imshow("滑动条", img1);
	value = 100;  // 初始值
	createTrackbar("亮度百分比", "滑动条", &value, 600, callBack, 0);
	 // 如果第三个参数是全局变量,最后一个参数用默认就行
	waitKey();
}

static void callBack(int, void *)
{
	float a = value / 100.0;
	img2 = img1 * a;
	imshow("滑动条", img2);
	cout << value << endl;
}

鼠标响应

void cv::setMouseCallback	(	const String & 	winname, // 窗口名
								MouseCallback 	onMouse, // 回调函数
								void * 	userdata = 0   // 传递给回调函数的可选参数
)	
typedef void(* cv::MouseCallback) (int event, int x, int y, int flags, void *userdata)
响应事件,鼠标指针在图像的x,y坐标,响应标志,函数名可以任意设置。在鼠标状态改变时调用

在这里插入图片描述
在鼠标位于图像窗口内时,时刻检测鼠标状态,发生改变时调用回调函数,根据回调函数中的判断逻辑执行响应的操作。比如,回调函数只处理左键按下事件,即判断event标志是否为 EVENT_LBUTTONDOWN, 当左键按下,执行对应的逻辑操作。

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

Mat img, imgPoint;
Point prePoint;
void mouse(int event, int x, int y, int flags, void *);

int main()
{
	img = imread("lena.png");
	img.copyTo(imgPoint);
	
	imshow("1", img);
	namedWindow("2", 0);
	imshow("2", imgPoint);
	setMouseCallback("1", mouse, 0);
	waitKey(0);
	return 0;
}

void mouse(int event, int x, int y, int flags, void *)
{
	if (event == EVENT_RBUTTONDOWN) // 右键单击
	{
		cout << "nonono";
	}
	if (event == EVENT_LBUTTONDOWN) // 左键单击
	{
		prePoint = Point(x, y);
		cout << "起始坐标" << prePoint << endl;
	}
	if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)) // 按住左键移动
	{
		//通过改变图像像素显示鼠标移动轨迹
		imgPoint.at<Vec3b>(y, x) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y, x - 1) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y, x + 1) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);
		imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);
		imshow("2", imgPoint);

		//通过绘制直线显示鼠标移动轨迹
		Point pt(x, y);
		line(img, prePoint, pt, Scalar(0, 0, 255), 2, 5, 0);
		prePoint = pt;
		imshow("1", img);
	}
}

小结

函数说明
circle\line\ellipse\ellipse2Poly\rectangle\fillPoly\putText画画
copyTo深拷贝
pyrDown/pyrUp下采样,上采样
createTrackbar创建滑动条
setMouseCallback鼠标响应
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 14:01:52  更:2021-08-14 14:03:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 20:59:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码