OpenCV-Python輪郭の特徴値を実現します。


前言
輪郭自体のいくつかの属性特徴および輪郭に囲まれたオブジェクトの特徴は、画像を記述する上で重要である。このブログでは、いくつかの輪郭自体の属性特徴と輪郭に囲まれたオブジェクトの特徴を紹介します。
アスペクト比
輪郭では、矩形の輪郭のアスペクト比のようなアスペクト比で輪郭を記述することができる。
アスペクト比=幅/高さ
次に、矩形の輪郭のアスペクト比を計算します。コードは以下の通りです。

import cv2

img = cv2.imread("26_1.jpg")
cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

x, y, w, h = cv2.boundingRect(contours[0])
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 3)
cv2.imshow("img1", img)

aspectRatio=float(w)/h
print(aspectRatio)

cv2.waitKey()
cv2.destroyAllWindows()
運転後、私たちは輪郭の幅の高さ比を約3とすることができます。
宽高比
エクステント
輪郭面積と矩形境界面積の比Extedを用いて画像とその輪郭特性を記述することもでき、数学的計算式図では:
Exted=輪郭面積/矩形境界面積
以下、Extedを計算します。コードは以下の通りです。

import cv2

img = cv2.imread("26_1.jpg")
cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

x, y, w, h = cv2.boundingRect(contours[0])
rectArea=w*h#      
cntArea=cv2.contourArea(contours[0])#    
extend=float(cntArea)/rectArea
print(extend)
この例では、輪郭面積と矩形境界面積の比は、Extedで約0.8である。
0.7
Solidity
輪郭面積と凸包面積の比Solidityを用いて画像,輪郭および凸包の特徴を測定することもできる。その数式は次の通りです。
Slidity=輪郭面積/凸包面積
以下、Slidityを計算します。コードは以下の通りです。

import cv2

img = cv2.imread("26_1.jpg")
cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

x, y, w, h = cv2.boundingRect(contours[0])
cntArea=cv2.contourArea(contours[0])#    
hull=cv2.convexHull(contours[0])
hullArea=cv2.contourArea(hull)#    
solidity=float(cntArea)/hullArea
print(solidity)
運転後、本例の輪郭面積と凸包面積の比は、ソニデリティの約1:
比例
等価直径
OpenCVでは輪郭面積に等しい円形の直径である等価直径を用いて輪郭の固有値を測定することもできる。その数式は次の通りです。
等效直径
次に、輪郭面積に等しい円形直径を計算します。コードは以下の通りです。

import cv2
import numpy as np

img = cv2.imread("26_1.jpg")
cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

x, y, w, h = cv2.boundingRect(contours[0])
cntArea=cv2.contourArea(contours[0])#    
equiDiameter=np.sqrt(4*cntArea/np.pi)
print(equiDiameter)
cv2.circle(img,(100,100),int(equiDiameter/2),(0,255,0),3)
cv2.imshow("img1",img)
cv2.waitKey()
cv2.destroyAllWindows()
運転後、私たちはその等価直径を約145として得た。
等效直径
方向
OpenCVでは、関数cv 2.fitEllipse()を用いて、最適なフィット楕円を構築することができ、また、戻り値内でそれぞれ楕円の中心点、軸長、回転角度情報を返すことができます。この形式を用いると,楕円の方向などの情報を直感的に得ることができる。
関数cv 2.fitEllipse()の戻り値は以下の通りです。
(x,y):楕円の中心点
(MA,ma):楕円水平方向軸と垂直方向軸の長さ
アングル:楕円の回転角度

import cv2

img = cv2.imread("26_1.jpg")
cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

ellipsis=cv2.fitEllipse(contours[0])

(x, y), (MA, ma), angle = cv2.fitEllipse(contours[0])

print((x, y), (MA, ma), angle)

cv2.ellipse(img, ellipsis, (0, 255, 0), 2)
cv2.imshow("img1", img)
cv2.waitKey()
cv2.destroyAllWindows()
元は楕円図です。下にフィットしたらちょうど楕円形です。
椭圆
マスクとピクセルポイント
あるオブジェクトのマスク画像とその対応点を取得するような場合もあります。OpenCVでは、cv 2.findNonZero()関数を提供して、画像内の輪郭点位置を取得します。その完全な定義は以下の通りです。

def findNonZero(src, idx=None): 
src:ゼロではない要素の画像を検索します。
idx:値を返し、0以外の要素の索引位置を表します。具体的な書式は(行番号、列番号)です。
以下、この関数を実測します。コードは以下の通りです。

import cv2
import numpy as np

img = cv2.imread("26_1.jpg")

cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

mask=np.zeros(gray.shape,np.uint8)
cv2.drawContours(mask,[contours[0]],0,255,2)
pixelpoints=cv2.findNonZero(mask)
print(pixelpoints)

cv2.imshow("img1", mask)
cv2.waitKey()
cv2.destroyAllWindows()
運転後、輪郭点の位置が得られます。
轮廓点位置
最大値、最小値、およびその位置
OpenCVでは、cv 2.minMaxLoc()関数が指定されたオブジェクト内の最大値、最小値、位置などの情報を提供します。その完全な定義は以下の通りです。

def minMaxLoc(src, mask=None): 
src:単一チャンネル画像
mark:マスクを使って、マスク指定エリア内の最値情報を得ます。
関数は4つの値を返します。最小値、最大値、最小値位置、最大値の位置です。
以下、これらの値を取得します。コードは以下の通りです。

import cv2
import numpy as np

img = cv2.imread("26_1.jpg")

cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

mask = np.zeros(gray.shape, np.uint8)
cv2.drawContours(mask, [contours[0]], 0, 255, 2)

min, max, min_loc, max_loc = cv2.minMaxLoc(gray, mask)
print(min, max, min_loc, max_loc)
運転後、コンソールから4つの値を出力します。
最小值
平均色と平均階調
OpenCVでは、cv 2.mean()関数を提供して、オブジェクトの平均色と平均階調を計算します。その完全な定義は以下の通りである。

def mean(src, mask=None):
パラメータは上の2つの小節と同じで、ここでは詳しく説明しない。以下、この関数を使います。コードは以下の通りです。

import cv2
import numpy as np

img = cv2.imread("26_1.jpg")


cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

mask=np.zeros(gray.shape,np.uint8)
cv2.drawContours(mask,[contours[0]],0,255,2)

mean=cv2.mean(img,mask)
運転後、4つの値を出力します。RGB及びAチャネルの平均値:
颜色平均值
極点
ある時、私達はある対象内の極点を獲得したいです。例えば、一番左、一番上、一番下などです。OpenCVでは、以下の方法を提供してくれます。

left=tuple(cnt[cnt[:,:,0].argmin()][0])
right=tuple(cnt[cnt[:,:,0].argmax()][0])
top=tuple(cnt[cnt[:,:,1].argmin()][0])
bottom=tuple(cnt[cnt[:,:,1].argmax()][0])
以下、これらの方法で取得します。コードは以下の通りです。

import cv2
import numpy as np

img = cv2.imread("26_1.jpg")

cv2.imshow("img", img)

#        
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

mask = np.zeros(img.shape, np.uint8)
cnt = contours[0]
left = tuple(cnt[cnt[:, :, 0].argmin()][0])
right = tuple(cnt[cnt[:, :, 0].argmax()][0])
top = tuple(cnt[cnt[:, :, 1].argmin()][0])
bottom = tuple(cnt[cnt[:, :, 1].argmax()][0])

print(left, right, top, bottom)

font = cv2.FONT_HERSHEY_SIMPLEX

cv2.putText(img, "left", left, font, 1, (0, 255, 0), 2)
cv2.putText(img, "right", right, font, 1, (0, 255, 0), 2)
cv2.putText(img, "top", top, font, 1, (0, 255, 0), 2)
cv2.putText(img, "bottom", bottom, font, 1, (0, 255, 0), 2)

cv2.imshow("result",img)
cv2.waitKey()
cv2.destroyAllWindows()
運転後の値と効果は以下の通りです。
上下左右
ここで、OpenCV-Pythonの輪郭を実現する特徴値についての記事を紹介します。OpenCVの輪郭に関する特徴値の内容は以前の文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。