OpenCV 輪郭認識 - 長さソート 最も値の検出 エッジ勾配検出 Python

最近、泡の輪郭認識に関連する作業を行うために opencv-python が使用されていますが、実装する必要がある機能は、泡画像の外側の輪郭を見つけることです。

3 つの部分に分かれています:

1. 輪郭の認識と長さによるソート、2. 特定の輪郭の最高点、最低点、左端、右端の点の検索、3. 内側輪郭と外側輪郭の判定。


1. 輪郭認識と長さによる分類

 元の画像:

画像の読み取り、前処理、輪郭認識: 

# 定义显示函数
def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

# 读取图片 灰度和彩色都要读取
img = cv2.imread('bub.png',cv2.IMREAD_GRAYSCALE)
img_rgb = cv2.imread('bub.png')
# 二值化
ret, image_threshold = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
cv2.imshow(image_threshold, image_threshold )
cv2.waitKey()
# 轮廓识别
contours, hierarchy = cv2.findContours(image_threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

 二値化後の画像:

 

 輪郭認識: cv2.findContours を使用して輪郭情報を返します。

輪郭ソート:

# 创建带有轮廓编号和长度的二维数组cnt_size
cnt_size = np.zeros((len(contours), 2), dtype = int)
for i in range(len(contours)):
    len_cnt = np.size(contours[i])
    if len_cnt > 6:
        cnt_size[i][0] = i
        cnt_size[i][1] = len_cnt
cnt_size = cnt_size[np.lexsort(cnt_size.T)]
sort_cnt = cv2.drawContours(img_rgb, contours, cnt_size[-2][0], (215, 19, 225), 2)
cv_show(sort_cnt,'sort_cnt')

 認識効果: 最も長い輪郭は最も外側の円であり、2 番目に長い輪郭は位置を特定する必要があるバブルの外側の輪郭です。

2. 特定の輪郭の最高点、最低点、左端の点、右端の点を検索します。 

# 确定需要查找的轮廓
contour = np.array(contours[cnt_size[-2][0]])
# 寻找上下左右四最值点
left_most = contour[contour[:, :, 0].argmin()][0]
right_most = contour[contour[:, :, 0].argmax()][0]
top_most = contour[contour[:, :, 1].argmin()][0]
bottom_most = contour[contour[:, :, 1].argmax()][0]
# 画线检验
cv2.line(img_rgb, (0, 0), left_most, (255, 25, 25), 2)
cv2.line(img_rgb, (0, 0), right_most, (25, 255, 255), 2)
cv2.line(img_rgb, (0, 0), top_most, (255, 255, 25), 2)
cv2.line(img_rgb, (0, 0), bottom_most, (55, 25, 255), 2)
cv_show(img_rgb,'img_line')

 線画効果:

3. 内外輪郭の判定

sobel 演算子に基づいて、左の黒と右の白、左の白と右の黒、上の黒と下の白、上の白と下の黒を効果的に識別できます。

# 使用sobel算子计算x、y方向上的梯度
sobelx = cv2.Sobel(image_threshold, cv2.CV_64F, 1, 0, ksize = 5)
sobely = cv2.Sobel(image_threshold, cv2.CV_64F, 0, 1, ksize = 5)
cv_show(sobelx,'sobelx')
cv_show(sobely,'sobely')
# 输出四个最值点的梯度信息
print(sobelx[left_most[1], left_most[0]], sobelx[right_most[1], right_most[0]])
print(sobely[top_most[1], top_most[0]], sobely[bottom_most[1], bottom_most[0]])

グラデーション画像:

出力結果: ここで、sobelx で使用される x 座標と y 座標の位置と、返される最大値の点の座標が逆であることに注意してください。

-9690.0 9690.0
-9690.0 9690.0

次に、正と負の値に従って外側の輪郭であるかどうかを判断します。

left = sobelx[left_most[1], left_most[0]]
right = sobelx[right_most[1], right_most[0]]
top = sobely[top_most[1], top_most[0]]
bottom = sobely[bottom_most[1], bottom_most[0]]
if left < 0 and right > 0 and top < 0 and bottom > 0:
    print('True')
else:
    print('False')

コード全体は次のとおりです。

import cv2 #opencv读取的格式是BGR
import numpy as np

def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
    
# 一、轮廓识别并按长度排序
# 读取图片 灰度和彩色都要读取
img = cv2.imread('bub1.png',cv2.IMREAD_GRAYSCALE)
img_rgb = cv2.imread('bub1.png')
cv_show(img_rgb,'img_rgb')

# 二值化
ret, image_threshold = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
cv_show(image_threshold,'image')

# 二、特定轮廓的最高点、最低点、最左点、最右点查找 
# 轮廓识别
contours, hierarchy = cv2.findContours(image_threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 创建带有轮廓编号和长度的二维数组cnt_size
cnt_size = np.zeros((len(contours), 2), dtype = int)
for i in range(len(contours)):
    len_cnt = np.size(contours[i])
    if len_cnt > 6:
        cnt_size[i][0] = i
        cnt_size[i][1] = len_cnt
cnt_size = cnt_size[np.lexsort(cnt_size.T)]
sort_cnt = cv2.drawContours(img_rgb, contours, cnt_size[-2][0], (215, 19, 225), 2)
cv_show(sort_cnt,'sort_cnt')
# 开始画线
contour = np.array(contours[cnt_size[-2][0]])
# 寻找上下左右四最值点
left_most = contour[contour[:, :, 0].argmin()][0]
right_most = contour[contour[:, :, 0].argmax()][0]
top_most = contour[contour[:, :, 1].argmin()][0]
bottom_most = contour[contour[:, :, 1].argmax()][0]
# 画线检验
cv2.line(img_rgb, (0, 0), left_most, (255, 25, 25), 2)
cv2.line(img_rgb, (0, 0), right_most, (25, 255, 255), 2)
cv2.line(img_rgb, (0, 0), top_most, (255, 255, 25), 2)
cv2.line(img_rgb, (0, 0), bottom_most, (55, 25, 255), 2)
cv_show(img_rgb,'img_line')

# 三、内外轮廓判断
# 使用sobel算子计算x、y方向上的梯度
sobelx = cv2.Sobel(image_threshold, cv2.CV_64F, 1, 0, ksize = 5)
sobely = cv2.Sobel(image_threshold, cv2.CV_64F, 0, 1, ksize = 5)
cv_show(sobelx,'sobelx')
cv_show(sobely,'sobely')
# 输出四个最值点的梯度信息
# 是反着的!!!!!!!!!!!!!!!!!!!!!
print(sobelx[left_most[1], left_most[0]], sobelx[right_most[1], right_most[0]])
print(sobely[top_most[1], top_most[0]], sobely[bottom_most[1], bottom_most[0]])
# 输出
left = sobelx[left_most[1], left_most[0]]
right = sobelx[right_most[1], right_most[0]]
top = sobely[top_most[1], top_most[0]]
bottom = sobely[bottom_most[1], bottom_most[0]]
if left < 0 and right > 0 and top < 0 and bottom > 0:
    print('True')
else:
    print('False')

おすすめ

転載: blog.csdn.net/weixin_41467446/article/details/126445022
おすすめ