opencv求解區(qū)域的內(nèi)接矩形
實(shí)驗(yàn)室項(xiàng)目中,希望求取一個(gè)近似圓形區(qū)域的質(zhì)心,原本使用最小外接圓的質(zhì)心來(lái)等效為該區(qū)域質(zhì)心。但是由于部分區(qū)域的形狀過(guò)于不規(guī)則導(dǎo)致發(fā)生質(zhì)心偏移現(xiàn)象。如下圖:

藍(lán)色為實(shí)際要求質(zhì)心。紅色為等效圓質(zhì)心
為獲取較為準(zhǔn)確的質(zhì)心,擬用最大內(nèi)接矩形的中心作為該區(qū)域質(zhì)心。
采用改進(jìn)的中心擴(kuò)散法求內(nèi)接矩形:先以最小外接矩的中心作為算法的起點(diǎn)進(jìn)行中心擴(kuò)散。得到一個(gè)內(nèi)解矩形,在對(duì)最小外接矩的中心進(jìn)行8鄰域的遍歷,應(yīng)用中心擴(kuò)散法分別求取內(nèi)接矩,以面積最大的內(nèi)接矩作為最大內(nèi)接矩。
使用Opencv關(guān)鍵代碼如下:
/**
* @brief 求取連通區(qū)域內(nèi)接矩
* @param img:輸入圖像,單通道二值圖,深度為8
* @param center:最小外接矩的中心
* @return 最大內(nèi)接矩形
* 基于中心擴(kuò)展算法
*/
cv::Rect InSquare(Mat &img,const Point center)
{
// --[1]參數(shù)檢測(cè)
if(img.empty()||
img.channels()>1
||img.depth()>8)
return Rect();
//[1]
// --[2] 初始化變量
int edge[4];
edge[0]=center.y+1;//top
edge[1]=center.x+1;//right
edge[2]=center.y-1;//bottom
edge[3]=center.x-1;//left
//[2]
// --[3]邊界擴(kuò)展(中心擴(kuò)散法)
bool EXPAND[4]={1,1,1,1};//擴(kuò)展標(biāo)記位
int n=0;
while (EXPAND[0]||EXPAND[1]||EXPAND[2]||EXPAND[3])
{
int edgeID=n%4;
EXPAND[edgeID]=expandEdge(img,edge,edgeID);
n++;
}
//[3]
qDebug()<<edge[0]<<edge[1]<<edge[2]<<edge[3];
Point tl=Point(edge[3],edge[0]);
Point br=Point(edge[1],edge[2]);
return Rect(tl,br);
}
/**
* @brief expandEdge 擴(kuò)展邊界函數(shù)
* @param img:輸入圖像,單通道二值圖,深度為8
* @param edge 邊界數(shù)組,存放4條邊界值
* @param edgeID 當(dāng)前邊界號(hào)
* @return 布爾值 確定當(dāng)前邊界是否可以擴(kuò)展
*/
bool expandEdge(const Mat & img, int edge[], const int edgeID)
{
//[1] --初始化參數(shù)
int nc=img.cols;
int nr=img.rows;
switch (edgeID) {
case 0:
if(edge[0]>nr)
return false;
for(int i=edge[3];i<=edge[1];++i)
{
if(img.at<uchar>(edge[0],i)==0)
return false;
}
edge[0]++;
return true;
break;
case 1:
if(edge[1]>nc)
return false;
for(int i=edge[2];i<=edge[0];++i)
{
if(img.at<uchar>(i,edge[1])==0)
return false;
}
edge[1]++;
return true;
break;
case 2:
if(edge[2]<0)
return false;
for(int i=edge[3];i<=edge[1];++i)
{
if(img.at<uchar>(edge[2],i)==0)
return false;
}
edge[2]--;
return true;
break;
case 3:
if(edge[3]<0)
return false;
for(int i=edge[2];i<=edge[0];++i)
{
if(img.at<uchar>(i,edge[3])==0)
return false;
}
edge[3]--;
return true;
break;
default:
return false;
break;
}
}
效果:

黑色為內(nèi)接矩中心,紅色為最小外接圓中心
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解C++內(nèi)存的代碼區(qū),全局區(qū),棧區(qū)和堆區(qū)
這篇文章主要為大家介紹了C++內(nèi)存的代碼區(qū),全局區(qū),棧區(qū)和堆區(qū),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12
C++開(kāi)發(fā)之PugiXML庫(kù)基礎(chǔ)用法示例詳解
PugiXML庫(kù)是一個(gè)功能強(qiáng)大、簡(jiǎn)單易用的C++ XML解析庫(kù),它提供了一組方便的函數(shù)來(lái)解析、創(chuàng)建和修改XML文檔,本文介紹了如何使用PugiXML庫(kù)來(lái)解析、創(chuàng)建和修改XML文檔,以及如何處理錯(cuò)誤和異常,感興趣的朋友跟隨小編一起看看吧2024-03-03
C語(yǔ)言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)迷宮實(shí)驗(yàn)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)迷宮實(shí)驗(yàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03
C++ OpenCV實(shí)戰(zhàn)之圖像全景拼接
本文主要介紹了如何使用OpenCV C++ 進(jìn)行圖像全景拼接,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)OpenCV有一定的幫助,感興趣的可以了解一下2022-01-01

