使用OpenCV檢測(cè)圖像中的矩形
本文實(shí)例為大家分享了OpenCV檢測(cè)圖像中矩形的具體代碼,供大家參考,具體內(nèi)容如下
前言
1.OpenCV沒(méi)有內(nèi)置的矩形檢測(cè)的函數(shù),如果想檢測(cè)矩形,要自己去實(shí)現(xiàn)。
2.我這里使用的OpenCV版本是3.30.
矩形檢測(cè)
1.得到原始圖像之后,代碼處理的步驟是:
(1)濾波增強(qiáng)邊緣。
(2)分離圖像通道,并檢測(cè)邊緣。
(3) 提取輪廓。
(4)使用圖像輪廓點(diǎn)進(jìn)行多邊形擬合。
(5)計(jì)算輪廓面積并得到矩形4個(gè)頂點(diǎn)。
(6)求輪廓邊緣之間角度的最大余弦。
(7)畫(huà)出矩形。
2.代碼
//檢測(cè)矩形
//第一個(gè)參數(shù)是傳入的原始圖像,第二是輸出的圖像。
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);
//濾波增強(qiáng)邊緣檢測(cè)
medianBlur(src, dst, 9);
//bilateralFilter(src, dst, 25, 25 * 2, 35);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
//在圖像的每個(gè)顏色通道中查找矩形
for (int c = 0; c < image.channels(); c++)
{
int ch[] = { c, 0 };
//通道分離
mixChannels(&dst, 1, &gray_one, 1, ch, 1);
// 嘗試幾個(gè)閾值
for (int l = 0; l < N; l++)
{
// 用canny()提取邊緣
if (l == 0)
{
//檢測(cè)邊緣
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;
// 檢測(cè)所找到的輪廓
for (size_t i = 0; i < contours.size(); i++)
{
//使用圖像輪廓點(diǎn)進(jìn)行多邊形擬合
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
//計(jì)算輪廓面積后,得到矩形4個(gè)頂點(diǎn)
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.運(yùn)行結(jié)果


以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Python使用Opencv實(shí)現(xiàn)圖像特征檢測(cè)與匹配的方法
- python opencv檢測(cè)目標(biāo)顏色的實(shí)例講解
- 10個(gè)步驟Opencv輕松檢測(cè)出圖片中條形碼
- Python 使用Opencv實(shí)現(xiàn)目標(biāo)檢測(cè)與識(shí)別的示例代碼
- Python Opencv實(shí)現(xiàn)單目標(biāo)檢測(cè)的示例代碼
- Opencv Hough算法實(shí)現(xiàn)圖片中直線檢測(cè)
- OpenCV實(shí)現(xiàn)圖像角點(diǎn)檢測(cè)
- opencv?canny邊緣檢測(cè)算法詳解
- 基于OpenCV的路面質(zhì)量檢測(cè)的實(shí)現(xiàn)
- opencv實(shí)現(xiàn)礦石圖片檢測(cè)礦石數(shù)量
相關(guān)文章
C++中為什么要使用動(dòng)態(tài)內(nèi)存
大家好,本篇文章主要講的是C++中為什么要使用動(dòng)態(tài)內(nèi)存,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-02-02
C++實(shí)現(xiàn)LeetCode(111.二叉樹(shù)的最小深度)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(111.二叉樹(shù)的最小深度),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++中用指向數(shù)組的指針作函數(shù)參數(shù)
多維數(shù)組名作為函數(shù)參數(shù)傳遞:在二維數(shù)組中,數(shù)組名a是指向首行a[0]的指針,也就是說(shuō)a=&a[0]; a[0]是指向首元素a[0][0]的指針,也就是說(shuō)a[0]=&a[0][0]2013-10-10
C語(yǔ)言實(shí)現(xiàn)基于最大堆和最小堆的堆排序算法示例
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)基于最大堆和最小堆的堆排序算法示例,分別是基于最大堆的升序排序和基于最小堆的降序排序?qū)嵗?需要的朋友可以參考下2016-06-06
C++實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05

