【OpenCV】绘图与注释——绘制色差图

   由于一些特殊原因,需要将色差图显示在Qt绘制的软件界面中。由于调用matlab编译动态库的运行效率较低,因此采用OpenCV提供的绘图与注释功能来绘制色差图。其最终效果如图1所示,图中camera数据由imx347模组拍摄的X-Rite 24色卡,在经过简单的去马赛克和白平衡处理后得到的数据值;而idea数据则为CIE标准值。
Alt

图1 色差图效果示意
   绘制色差图,需要使用到OpenCV提供的直线、矩形、圆、文字等绘制方法。绘制色差图所使用的函数已经在表1中给出。
表1 色差图使用的绘图与注释函数
函数描述
cv::circle()画一个简单的圆
cv::line()画一条简单的直线
cv::rectangle()画一个简单的矩形
cv::putText()在图像中绘制指定的文字

  

关于绘制色差图,主要经过了以下步骤:

  1. 准备Camera数据,并将数据从rgb域转换到lab域;
  2. 绘制色差图背景;
  3. 绘制camera、idea数据点,并将数据点连线,打印色卡块序号;
  4. 添加camera、idea图例;

1. 准备数据,并将数据从rgb域转换到lab域。在此仅给出rgb转lab域的函数,并未给出具体的色块数据。

/*
	描述: rgb -> lab
	输入:存储rgb信息的矩阵(24 * 3)
	输出:L, a, b数据值
*/
void rgb2lab(Mat src, Mat *L, Mat *a, Mat *b)
{
	Mat rgbchannel[3], labchannel[3], rgb, lab;
	rgbchannel[0] = src.colRange(0, 1).clone();
	rgbchannel[1] = src.colRange(1, 2).clone();
	rgbchannel[2] = src.colRange(2, 3).clone();

	// rgb——>lab
	merge(rgbchannel, 3, rgb);
	cvtColor(rgb, lab, COLOR_RGB2Lab);
	split(lab, labchannel);

	(*L) = labchannel[0].clone();
	(*a) = labchannel[1].clone();
	(*b) = labchannel[2].clone();
}

2. 绘制色差图背景。

/*
	描述:与matlab meshgrid功能相同
*/
void meshgrid(const Range xr, const Range yr, float step, Mat &outX, Mat &outY)
{
	vector<float> x, y;
	for (float i = xr.start; i <= xr.end; i += step)
		x.push_back(i);
	for (float i = yr.start; i <= yr.end; i += step)
		y.push_back(i);

	repeat(Mat(x).t(), y.size(), 1, outX);
	repeat(Mat(y), 1, x.size(), outY);
}

/*
	描述:生成色差图背景
	返回:色差图背景
*/
Mat createBackground()
{
	Mat a, b, lab, rgb, channel[3];

	// 准备数据
	meshgrid(Range(-80, 100), Range(-80, 120), 0.1, a, b);		// 生成网格
	Mat L = Mat::ones(a.size(), CV_32FC1);
	L = L.mul(90);
	L.row(800) = 50;
	L.col(800) = 50;
	a.convertTo(a, CV_32FC1);
	b.convertTo(b, CV_32FC1);
	
	// 生成背景
	channel[0] = L;
	channel[1] = a;
	channel[2] = b;
	merge(channel, 3, lab);
	cvtColor(lab, rgb, COLOR_Lab2BGR);
	flip(rgb, rgb, 0);

	return rgb;
}

3. 绘制camera、idea数据点,并将数据点连线,打印色卡块序号;

for (int i = 0; i < 24; i++)
{
	// 指定颜色
	float colorR = target.at<float>(i, 0);
	float colorG = target.at<float>(i, 1);
	float colorB = target.at<float>(i, 2);

	// 绘制idea数据点
	int ix = calculateCoordinate((int)ideaa.at<float>(i, 0), Range(-80, 100));
	int iy = calculateCoordinate((int)ideab.at<float>(i, 0), Range(-80, 120));
	cv::Point ipoint;
	ix = ix * 10;
	iy = 2001 - iy * 10;
	ipoint.x = ix;
	ipoint.y = iy;
	circle(rgb, ipoint, 11, Scalar(0.4, 0.4, 0.4), 3, LINE_AA);
	circle(rgb, ipoint, 10, Scalar(colorB, colorG, colorR), -1, LINE_AA);

	// 绘制camera数据值
	int cx = calculateCoordinate((int)curta.at<float>(i, 0), Range(-80, 100));
	int cy = calculateCoordinate((int)curtb.at<float>(i, 0), Range(-80, 120));
	cx = cx * 10;
	cy = 2001 - cy * 10;
	cv::Point cpoint;
	cpoint.x = cx;
	cpoint.y = cy;
	Rect rectedge = Rect(cx - 9, cy - 9, 17, 17);
	Rect rect = Rect(cx - 8, cy - 8, 15, 15);
	rectangle(rgb, rectedge, Scalar(0.4, 0.4, 0.4), 3, LINE_AA);
	rectangle(rgb, rect, Scalar(colorB, colorG, colorR), -1, LINE_AA);

	// 连接idea值与camera数据值
	line(rgb, ipoint, cpoint, Scalar(colorB, colorG, colorR), 5, LINE_AA);

	// 打印色卡块序号
	string numlable = to_string(i+1);
	int x = (ix + cx) / 2;
	int y = (iy + cy) / 2; 
	putText(rgb, numlable, Point(x, y), FONT_HERSHEY_DUPLEX, 1, Scalar(0, 0, 0), 1, LINE_AA);
}

   由于背景是以Mat形式存储,因此在绘制数据点时,需要将a, b的值转换成Mat的横纵坐标。其转换函数如下

int calculateCoordinate(int value, const Range range)
{
	int count = 0;
	for (int i = range.start; i < range.end; i++)
	{
		if (value == i)
			return count;
		count++;
	}

	return -1;
}

4. 添加camera、idea图例。

// 打印camera值图例
Rect camera = Rect(150 - 10, 100 - 10, 20, 20);
rectangle(rgb, camera, Scalar(0.4, 0.4, 0.4), -1, LINE_AA);
string camerastr = "camera";
putText(rgb, camerastr, Point(170, 105), FONT_HERSHEY_DUPLEX, 1, Scalar(0, 0, 0), 1, LINE_AA);

// 打印理想值图例
circle(rgb, Point(150, 150), 11, Scalar(0.4, 0.4, 0.4), -1, LINE_AA);
string ideastr = "idea";
putText(rgb, ideastr, Point(170, 160), FONT_HERSHEY_DUPLEX, 1, Scalar(0, 0, 0), 1, LINE_AA);

说明:
   上述代码,采用VS2013+OpenCV3.0环境编译,且验证通过。使用者可自行准备camera和idea的数据进行验证。图1所示的色差图中,并未打印色差相关的信息,若有人使用源码,可根据自己的需求添加色差信息。

个人声明:
   以上内容,纯属个人观点,不喜勿喷。未经本人同意,不得私自转载。博客中出现的代码仅供学习参考,不得有其他用途。若文中存在纰漏,或读者有更好的建议,欢迎留言探讨。也可邮箱联系:yxyx_0212@163.com

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
opencv是一个开源的计算机视觉库,opencv2.4.9是其中的一个版本。在opencv2.4.9中,有一个模块叫做stitching,用于像拼接。 像拼接是将多张像按照一定的顺序和方式进行合并,形成一张更大视野覆盖范围的像。拼接的过程需要解决像间的重叠区域匹配、像变换与叠加等问题。 在opencv2.4.9的stitching模块中,主要有以下几个重要的类: 1. Stitcher类:拼接器类,用于执行拼接的主要操作。它提供了一系列的方法,如设置拼接的模式、添加要拼接的像等。 2. FeaturesFinder类:特征点检测类,用于在像中寻找特征点。该类利用SIFT、SURF等算法来检测像中的关键点,以便进行匹配。 3. FeaturesMatcher类:特征点匹配类,用于对像中的特征点进行匹配。该类使用KNN算法进行特征点的匹配,并利用RANSAC算法进一步筛选特征点,剔除误匹配。 4. Estimator类:变换估计类,用于估计像间的变换参数。该类可以通过特征点的对应关系,计算像间的旋转矩阵、平移矩阵等变换参数。 5. Blender类:像融合类,用于将拼接后的像进行融合。该类可以进行多种融合方式,如线性融合、多频融合等。 通过以上的类和方法,opencv2.4.9的stitching模块能够完成像拼接的过程。整个过程包括特征点检测、特征点匹配、变换参数估计和像融合等步骤。 需要指出的是,本文只是对opencv2.4.9的stitching模块进行了初步的介绍,具体的源码分析需要深入研究。整个源码工程庞大,包含很多细节和算法,需要对计算机视觉和像处理有较深入的理解才能进行分析和改进。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值