OpenCV图像处理技术(Python)——图像轮廓
© Fu Xianjun. All Rights Reserved.
文章目录
前言
根据上一篇的学习,一定对图像轮廓有了很多的理解,今天将继续学习图像轮廓。
学习目标
1.能够理解凸包的概念及使用方法
2.能够使用凸缺陷检测进行实际场景应用
3.能够掌握轮廓常见特征值
4.能够熟练运用轮廓特征值解决实际问题
学习内容
一、凸包的查找与绘制
1.凸包的概念
凸包指的是完全包含原有轮廓,并且仅由轮廓上的点所构成的多边形。凸包的每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部。在凸包内,任意连续三个点的内角小于180°。
2.凸包的获取
核心代码以及解释:
import cv2
# 读取图片并转至灰度模式
img = cv2.imread('contours2.png', 1)
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_NONE)
cnt = contours[0]
# 寻找凸包并绘制凸包(轮廓)
hull = cv2.convexHull(cnt)
cv2.polylines(img,[hull],True,(255,0,0),2)
# 显示图片
cv2.imshow('line', img)
cv2.waitKey()
cv2.destroyAllWindows()
代码运行结果:
3.凸包的绘制
核心代码以及解释:
二、凸缺陷检测
1.凸缺陷的概念
凸包与轮廓之间的部分,称为凸缺陷。轮廓上距离这条线最远的点就是凸缺陷的点。
2.凸缺陷
核心代码以及解释:
import cv2
o = cv2.imread('contours2.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_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
for i in range(defects.shape[0]):
s,e,f,d = defects[i,0]
start = tuple(cnt[s][0]) # 得到的是索引,要再轮廓中选出来
end = tuple(cnt[e][0])
far = tuple(cnt[f][0])
cv2.line(o,start,end,[0,0,255],2)
cv2.circle(o,far,5,[255,0,0],-1)
cv2.imshow('result',o)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:
三、廓常见特征值
1.宽高比
代码形式:
import cv2
o = cv2.imread('binaryhand.png')
cv2.imshow("original",o)
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)
x,y,w,h = cv2.boundingRect(contours[0])
cv2.rectangle(o,(x,y),(x+w,y+h),(255,255,255),3)
aspectRatio = float(w)/h
print(aspectRatio)
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()
2.Extend
代码形式:
import cv2
o = cv2.imread('binaryhand.png')
cv2.imshow("original",o)
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)
x,y,w,h = cv2.boundingRect(contours[0])
cv2.drawContours(o,contours[0],-1,(0,0,255),3)
cv2.rectangle(o,(x,y),(x+w,y+h),(255,0,0),3)
rectArea=w*h
cntArea=cv2.contourArea(contours[0])
extend=float(cntArea)/rectArea
print(extend)
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()
3.最大值和最小值及它们的位置
代码形式:
import cv2
import numpy as np
o = cv2.imread('ct2.jpg')
cv2.imshow("original",o)
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)
cnt=contours[3] #coutours[0]、coutours[1]是左侧字母R
#--------使用掩膜获取感兴趣区域的最值-----------------
#需要注意minMaxLoc处理的对象为灰度图像,本例中处理对象为灰度图像gray
#如果希望获取彩色图像的,需要提取各个通道,将每个通道独立计算最值
mask = np.zeros(gray.shape,np.uint8)
mask=cv2.drawContours(mask,[cnt],-1,255,-1)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(gray,mask = mask)
print("minVal=",minVal)
print("maxVal=",maxVal)
print("minLoc=",minLoc)
print("maxLoc=",maxLoc)
#--------使用掩膜获取感兴趣区域并显示-----------------
masko = np.zeros(o.shape,np.uint8)
masko=cv2.drawContours(masko,[cnt],-1,(255,255,255),-1)
loc=cv2.bitwise_and(o,masko)
cv2.imshow("mask",loc)
#显示灰度结果
#loc=cv2.bitwise_and(gray,mask)
#cv2.imshow("mask",loc)
#--------释放窗口-----------------
cv2.waitKey()
cv2.destroyAllWindows()
4.极点
代码形式:
import cv2
import numpy as np
o = cv2.imread('binaryhand.png')
o1 = cv2.imread("face.png")
o1 = cv2.resize(o1,(40,40))
#--------获取并绘制轮廓-----------------
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)
o[284:324,229:269]=o1
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()
cv2.destroyAllWindows()
总结
今天的轮廓学习就到这里,相信兄弟们是已经学会了。记得每个代码都要导包谢谢!