轮廓自身的一些属性特征及轮廓所包围对象的特征对于描述图像具有重要意义,本节介绍第二部分,包括像素点的位置信息、最大值/最小值及其位置、平均值、极点。

掩模和像素点

本节介绍如何获取轮廓(实心、空心)的像素点位置信息。

轮廓是图像内非零的像素点,可以通过两种方式获取轮廓像素点的位置信息。一种是使用Numpy函数,另外一种是使用OpenCV函数。

使用Numpy函数获取轮廓像素点

使用numpy.nonzero()函数能够找出数组内非零元素的位置,但是其返回值是将行、列分别显示的。

例:使用Numpu函数获取一个数组内的非零值元素的位置信息。

import numpy as np

# =====生成数组,随机位置为1=====
a =  np.zeros((5,5),dtype=np.uint8)
    #随机将十个位置替换为1
for times in range(10):         
    i = np.random.randint(0,5)
    j = np.random.randint(0,5)
    a[i,j] = 1

# =====观察原始数据=====
print('a=\n',a)

# =====非零值的位置=====
loc = np.transpose(np.nonzero(a))
print('a内非零值的位置:\n',loc)

运行结果:

a=
[[0 0 1 1 0]
[1 0 0 0 0]
[0 0 0 1 0]
[1 1 0 0 1]
[0 0 1 0 0]]
a内非零值的位置:
[[0 2]
[0 3]
[1 0]
[2 3]
[3 0]
[3 1]
[3 4]
[4 2]]

例2:使用Numpy函数获取一个图像内的轮廓点位置。

import cv2
import numpy as np

# =====读取原始图像=====
o = cv2.imread(r'E:\Blog\OpenCV\Process\A5.png')
cv2.imshow('ORIGINAL',o)

# =====获取轮廓=====
gray1 = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret,binary1 = cv2.threshold(gray1,127,255,cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(binary1,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]

# =====绘制空心轮廓=====
mask1 = np.zeros(gray1.shape,np.uint8)
cv2.drawContours(mask1,[cnt],0,255,2)
pixelpoints1 = np.transpose(np.nonzero(mask1))  #非零处的位置
print('pixelpoints1.shape=',pixelpoints1.shape)
print('pixelpoints1=',pixelpoints1)
cv2.imshow('mask1',mask1)

#在cv2.drawContours()的轮廓宽度参数设置为-1时,即可获得实心轮廓,即特定对象的掩模
# =====绘制实心轮廓=====
mask2 = np.zeros(gray1.shape,np.uint8)
cv2.drawContours(mask2,[cnt],0,255,-1)
pixelpoints2 = np.transpose(np.nonzero(mask2))  #非零处的位置
print('pixelpoints2.shape=',pixelpoints2.shape)
print('pixelpoints2=',pixelpoints2)
cv2.imshow('mask2',mask2)

cv2.waitKey()

运行结果:

pixelpoints1.shape= (3062, 2)
pixelpoints1= [[ 88 290]
[ 88 291]
[ 88 292]
...
[227 484]
[228 482]
[228 483]]
pixelpoints2.shape= (11405, 2)
pixelpoints2= [[ 89 291]
[ 89 292]
[ 89 293]
...
[226 481]
[226 482]
[227 483]]运行结果

使用OpenCV函数获取轮廓像素点

idx = cv2.findNonZero( src )
  • idx为返回值,表示非零元素的索引位置。每个元素对应的是(行号,列号)的格式
  • src为参数,表示要查找非零元素的图像

最大值和最小值及它们的位置

OpenCV提供了函数cv2.minMaxLoc(),用在指定的对象内查找最大值、最小值及其位置。

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(imgray,mask=mask)
  • min_val:最小值

  • max_val:最大值

  • min_loc:最小值的位置

  • max_loc:最大值的位置

  • imgray:单通道图像

  • mask:掩模

平均颜色及平均灰度

语法:

mean_val = cv2.mean(im, mask = mask)

例:使用函数cv2.mean()计算一个对象的平均灰度。

import cv2
import numpy as np

## =====读取原始图像=====
o = cv2.imread(r'E:\Blog\OpenCV\Process\A7.png')
cv2.imshow('ORIGINAL',o)

## =====获取轮廓=====
gray1 = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret,binary1 = cv2.threshold(gray1,127,255,cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(binary1,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[2]

# =====使用掩模获取感兴趣区域的均值=====
mask = np.zeros(gray1.shape, np.uint8) #构造mean所使用的掩模(必须是单通道的)
cv2.drawContours(mask,[cnt],0,(255,255,255),-1)
meanVal = cv2.mean(o,mask=mask)
print('meanVal=',meanVal)

# =====使用掩模获取感兴趣区域并显示=====
masko = np.zeros(o.shape,np.uint8)
cv2.drawContours(masko,[cnt],-1,(255,255,255),-1)
loc = cv2.bitwise_and(o,masko)
cv2.imshow('mask',loc)

cv2.waitKey()

运行结果:四个值分别是R、G、B和A通道四个值。

meanVal= (82.36522753792299, 82.36522753792299, 82.36522753792299, 0.0)

结果

极点

获取某个对象内的极值点,例如最左端、最右端、最上端、最下端的四个点。语法格式:

leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

例:计算一个图像内的极值点。

import cv2
import numpy as np
o = cv2.imread(r'E:\Blog\OpenCV\Process\C3.png')

# =====获取并绘制轮廓=====
gray = cv2.cvtColor(o,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)
cnt = contours[0]
cv2.drawContours(mask,[cnt],0,255,-1)

# =====计算极值=====
leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

# =====打印极值=====
print('leftmost=',leftmost)
print('rightmost=',rightmost)
print('topmost=',topmost)
print('bottommost=',bottommost)

# =====绘制文字说明=====
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(o,'A',leftmost,font,1,(0,0,255),2)
cv2.putText(o,'B',rightmost,font,1,(0,0,255),2)
cv2.putText(o,'C',topmost,font,1,(0,0,255),2)
cv2.putText(o,'D',bottommost,font,1,(0,0,255),2)

# =====绘制图像=====
cv2.imshow('RESULT',o)
cv2.waitKey()

运行结果:

leftmost= (67, 176)
rightmost= (375, 129)
topmost= (356, 28)
bottommost= (175, 202)

运行结果


博主个人公众号
版权声明 ▶ 本网站名称:陶小桃Blog
▶ 本文链接:https://www.52txr.cn/2022/OpenCV41.html
▶ 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行核实删除。
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

最后修改:2022 年 05 月 27 日
如果觉得我的文章对你有用,请随意赞赏