用opencv測量物體大概角度的乙個比較笨的思路

2021-10-11 17:40:31 字數 4410 閱讀 1773

檢測faster-rcnn或者yolo目標檢測演算法後的bbox中物體的大概角度。

1.首先將原圖分為bgr三個通道,將其中兩個通道加權求和之後進行灰度化,我這裡採用的是4g-1b,如果下一步驟的閾值分割效果不好,可以嘗試一下其他兩個通道加權求和。

mat mv[3]

;split

(src,mv)

;mat img;

addweighted

(mv[1]

,4,mv[0]

,-1,

0,img)

;

2.使用閾值分割,這裡推薦otsu閾值分割和迭代閾值分割,這兩種的效果最好,**如下

mat gray;

gray=

iterationthreshold

(img)

;

//otsu閾值分割

mat otsualgthreshold

(mat &image)

int t =0;

//otsu演算法閾值

double varvalue =0;

//類間方差中間值儲存

double w0 =0;

//前景畫素點數所佔比例

double w1 =0;

//背景畫素點數所佔比例

double u0 =0;

//前景平均灰度

double u1 =0;

//背景平均灰度

double histogram[

256]=;

//灰度直方圖,下標是灰度值,儲存內容是灰度值對應的畫素點總數

uchar *data = image.data;

double totalnum = image.rows*image.cols;

//畫素總數

for(

int i =

0; i < image.rows; i++)}

int minpos, maxpos;

for(

int i =

0; i <

255; i++)}

for(

int i =

255; i >

0; i--)}

for(

int i = minpos; i <= maxpos; i++)if

(w1 ==0)

//背景部分畫素點數為0時退出

u1 = u1 / w1;

//背景畫素平均灰度

w1 = w1 / totalnum;

// 背景部分畫素點數所佔比例

//***********背景各分量值計算**************************

//***********前景各分量值計算**************************

for(

int k = i +

1; k <

255; k++)if

(w0 ==0)

//前景部分畫素點數為0時退出

u0 = u0 / w0;

//前景畫素平均灰度

w0 = w0 / totalnum;

// 前景部分畫素點數所佔比例

//***********前景各分量值計算**************************

//***********類間方差計算******************************

double varvaluei = w0*w1*

(u1 - u0)

*(u1 - u0)

;//當前類間方差計算

if(varvalue < varvaluei)

} mat dst;

threshold

(image, dst, t,

255, cv_thresh_otsu)

;return dst;

}

//迭代閾值分割

mat iterationthreshold

(mat src)

;for

(int j =

0; j < height; j++

)int t0 =0;

for(

int i =

0; i <

256; i++

) t0 /

= width*height;

int t1 =

0, t2 =0;

int num1 =

0, num2 =0;

int t =0;

while(1

)if(num1 ==0)

continue

;for

(int i = t0 +

1; i <

256; i++)if

(num2 ==0)

continue

; t =

(t1 / num1 + t2 / num2)/2

;if(t == t0)

break

;else

t0 = t;

} mat dst;

threshold

(src, dst, t,

255,0)

;return dst;

}

3.膨脹處理

mat morphologydst;

cv::

morphologyex

(gray, morphologydst, cv::morph_dilate,

cv::

getstructuringelement

(cv::morph_rect, cv::

size(7

,1))

);

4.找出最小外接矩形,由於進行膨脹處理後,圖中還有一些黑點,沒有用孔洞填充,直接用乙個最笨的方法,由於圖中只有乙個物體,因此,可以遍歷其中所有的最小外接矩形,選出最大的乙個,就是要找的那個,也嘗試一下孔洞填充,但是感覺效果不咋地,孔洞填充**如下,需要的可以嘗試一下。

vector> contours;

vector hierarchy;

findcontours

point(0

,0))

;vector

minrect

(contours.

size()

);float area=0;

for(

int i =

0; i < contours.

size()

; i++

)

//孔洞填充

void

fillhole

(const mat srcbw, mat &dstbw)

5.將外接矩形框畫出,這裡有個比較重要的是,opencv提供的rotatedrect中的角度是相對角度,(-90,0],需要將其轉換為絕對角度。

mat drawing=src;

for(

int i =

0; i< contours.

size()

; i++

)}

//將相對角度轉化為絕對角度

static

double

calclinedegree

(const point2f& firstpt,

const point2f& secondpt)

}else

return curlineangle*

180.0f

/cv_pi;

}static

double

getrcdegree

(const rotatedrect box)

else

return degree;

}

檢測效果

判斷乙個遊戲物體在另乙個遊戲物體的左邊或者右邊

最近在公司專案裡面做乙個boss戰鬥,boss有兩個轉向動畫,乙個向左轉,乙個向右轉,轉向之前你首先需要判斷人物位置當前在boss的左邊還是右邊,可以使用 float result vector3.cross boss.transform.forward,人物到boss的向量 y 如果結果是正,則表...

MySQL 乙個簡單insert語句的大概流程

mysql create table testin id int query ok,0 rows affected 2.38 sec mysql insert into testin values 10 query ok,1 row affected 0.02 sec 126 t 2 thd ent...

登陸的乙個大概流程

登陸的乙個大概流程 1 接受登陸引數 2 引數的合法性檢驗 3 檢驗成功,執行使用者名稱是否存在的查詢 4 如果不存在該使用者,返回登陸頁面,並加入提示資訊 5 如果存在,檢驗密碼是否正確,如果密碼不正確,返回登陸頁面,加入提示資訊 6 密碼匹配正確的情況下,user使用者加入session,執行跳...