使用OpenCV檢測圖像中的矩形

前言

1.OpenCV沒有內置的矩形檢測的函數,如果想檢測矩形,要自己去實現。
2.我這裏使用的OpenCV版本是3.30.

矩形檢測

1.得到原始圖像之後,代碼處理的步驟是:
(1)濾波增強邊緣。
(2)分離圖像通道,並檢測邊緣。
(3) 提取輪廓。
(4)使用圖像輪廓點進行多邊形擬合。
(5)計算輪廓面積並得到矩形4個頂點。
(6)求輪廓邊緣之間角度的最大餘弦。
(7)畫出矩形。
2.代碼

//檢測矩形
//第一個參數是傳入的原始圖像,第二是輸出的圖像。
void findSquares(const Mat& image,Mat &out)
{
	int thresh = 50, N = 5;
	vector<vector<Point> > squares;
	squares.clear();

	Mat src,dst, gray_one, gray;

	src = image.clone();
	out = image.clone();
	gray_one = Mat(src.size(), CV_8U);
	//濾波增強邊緣檢測
	medianBlur(src, dst, 9);
	//bilateralFilter(src, dst, 25, 25 * 2, 35);

	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;

	//在圖像的每個顏色通道中查找矩形
	for (int c = 0; c < image.channels(); c++)
	{
		int ch[] = { c, 0 };

		//通道分離
		mixChannels(&dst, 1, &gray_one, 1, ch, 1);

		// 嘗試幾個閾值
		for (int l = 0; l < N; l++)
		{
			// 用canny()提取邊緣
			if (l == 0)
			{
				//檢測邊緣
				Canny(gray_one, gray, 5, thresh, 5);
				//膨脹
				dilate(gray, gray, Mat(), Point(-1, -1));
				imshow("dilate", gray);
			}
			else
			{
				gray = gray_one >= (l + 1) * 255 / N;
			}

			// 輪廓查找
			//findContours(gray, contours, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
			findContours(gray, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);

			vector<Point> approx;
			
			// 檢測所找到的輪廓
			for (size_t i = 0; i < contours.size(); i++)
			{
				//使用圖像輪廓點進行多邊形擬合
				approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

				//計算輪廓面積後,得到矩形4個頂點
				if (approx.size() == 4 &&fabs(contourArea(Mat(approx))) > 1000 &&isContourConvex(Mat(approx)))
				{
					double maxCosine = 0;

					for (int j = 2; j < 5; j++)
					{
						// 求輪廓邊緣之間角度的最大餘弦
						double cosine = fabs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));
						maxCosine = MAX(maxCosine, cosine);
					}

					if (maxCosine < 0.3)
					{
						squares.push_back(approx);
					}
				}
			}
		}
	}

	
	for (size_t i = 0; i < squares.size(); i++)
	{
		const Point* p = &squares[i][0];

		int n = (int)squares[i].size();
		if (p->x > 3 && p->y > 3)
		{
			polylines(out, &p, &n, 1, true, Scalar(0, 255, 0), 3, LINE_AA);
		}
	}
	imshow("dst",out);
}

static double angle(Point pt1, Point pt2, Point pt0)
{
	double dx1 = pt1.x - pt0.x;
	double dy1 = pt1.y - pt0.y;
	double dx2 = pt2.x - pt0.x;
	double dy2 = pt2.y - pt0.y;
	return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

3.運行結果
在這裏插入圖片描述
在這裏插入圖片描述

發佈了69 篇原創文章 · 獲贊 38 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章