从图像中提取特定颜色区域。

作业:

利用 OpenCV 实现:分别找出 images 中 3 张图片里的蓝色指示牌和绿色指示牌,并将它们
写入到 green、blue 两个文件夹中。
要求:
1. 用矩形框出指示牌
2. 写入的指示牌需要 尽量拉正
运行结果如下图:

 思路:

1、转化成HSV,找出相应颜色对应的范围,用inRange函数提取出来。(这个一定要注意,不同的颜色的范围,我也是刚开始做,在找范围(scalar(a,b,c)时不断尝试才提取出来。)

2、找出相应轮廓并将轮廓画出。

3、用最小外接矩形,找出要提取的矩阵。

4、将找出矩形的四个顶点按照顺时针顺序排除。

5、运用三点法的仿射变换,找出变化前和变化后的坐标位置。

#include<iostream>
#include<cmath>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat srcImage = imread("D://RM//OpenCv的学习//图像中提取一特定矩形//test2.png");
	if (!srcImage.data)
	{
		cout << "读取图片错误,请重新输入正确路径!\n";
		system("pause");
		return -1;
	}
	Mat srcHSV;
	cvtColor(srcImage, srcHSV, COLOR_BGR2HSV);

	Mat dstImage;
	int ZYW;
	cout << "如果提取蓝色牌子请输入1 ,如果提取绿色牌子请输入2" << endl;
	cin >> ZYW;
	if(ZYW==1){ inRange(srcHSV, Scalar(100, 120, 125), Scalar(124, 220, 255), dstImage); }
	else if(ZYW==2){ inRange(srcHSV, Scalar(56, 90, 80), Scalar(90, 255, 200), dstImage); }

	imshow("【利用inRange()函数实现阈值化】", dstImage);
	Mat element = getStructuringElement(MORPH_RECT, Size(1, 2));
	vector<vector<Point>> contours;
	vector<Point> contour;
	vector<Vec4i> hierarchy;
	findContours(dstImage, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
	//轮廓绘制
	Mat drawImage;
	double width = srcImage.cols;
	double height = srcImage.rows;

	Mat dst = Mat::zeros(srcImage.size(), CV_8UC3);
	cout << contours.size() << endl;
	for (int t = 0; t < contours.size(); t++)
	{
		double length2 = arcLength(contours[t], true);
		cout << "第" << t << "个轮廓长度=" << length2 << endl;
		if (length2 > 800) {
			contour = contours[t];
			Scalar color = Scalar(250, 120, 220);
			drawContours(srcImage, contours, t, color, 2, 8, hierarchy, 0, Point(0, 0));
		}
	}
	namedWindow("output", WINDOW_AUTOSIZE);
	imshow("output", srcImage);
	RotatedRect rr = minAreaRect(contour);
	Point2f points[4];
	rr.points(points);
	Point2f points2[4];
	cout << "center.x = " << rr.center.x << "center.y = " << rr.center.y << endl;
	for (int i = 0; i < 4; i++) {
		if (points[i].x < rr.center.x) {
			if (points[i].y < rr.center.y) {
				points2[0] = points[i];
			}
			else if (points[i].y > rr.center.y) {
				points2[3] = points[i];
			}
		}
		else if (points[i].x > rr.center.x) {
			if (points[i].y > rr.center.y) {
				points2[2] = points[i];
			}
			else if (points[i].y < rr.center.y) {
				points2[1] = points[i];
			}
		}
	}
	for (int i = 0; i < 4; i++) {
		cout << points2[i].x << "  " << points2[i].y << endl;
	}
	double chang = sqrt((points2[1].y - points2[0].y) * (points2[1].y - points2[0].y) + (points2[1].x - points[0].x) * (points2[1].x - points[0].x));
	double kuan = sqrt((points2[3].y - points2[0].y) * (points2[3].y - points2[0].y) + (points2[3].x - points2[0].x) * (points2[3].x - points2[0].x));
	Point2f srcPoints[3];
	Point2f dstPoints[3];

	srcPoints[0] = points2[0];
	srcPoints[1] = points2[1];
	srcPoints[2] = points2[3];

	dstPoints[0] = Point2f(points2[0].x, points2[0].y);
	dstPoints[1] = Point2f(points2[0].x + chang, points2[0].y);
	dstPoints[2] = Point2f(points2[0].x, points2[0].y + kuan);

	Mat M1 = getAffineTransform(srcPoints, dstPoints);
	warpAffine(srcImage, srcImage, M1, srcImage.size());

	imshow("正", srcImage);

	Rect rect1(points[1].x, points[1].y, chang, kuan);
	Mat after_1;
	srcImage(rect1).copyTo(after_1);
	imshow("蓝色指示牌1", after_1);
	imwrite("result3.png", after_1);



	waitKey(0);
	return 0;
}

运行结果如下:

                                         

 第一次学,方法可能不是很好,若有不足请大家指正!!!

  • 6
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值