OpenCV——图像轮廓

我们的目标:

能够掌握轮廓查找与绘制的方法

能够掌握轮廓面积及长度的计算方法

能够编程实现形状匹配

能够掌握轮廓的几何形状拟合方法

任务一 凸包绘制

案例一 获取凸包

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()

练习:实物凸包检测

import cv2
# 读取图片并转至灰度模式
img = cv2.imread('hand.png', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, binary = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)
# 图片轮廓
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
n=len(contours)       #轮廓个数
contoursImg=[]
x=0 #初始化要绘制的轮廓索引
for i in range(n):
    area = cv2.contourArea(contours[i])
    if area>10000:    
        print(f"轮廓{i}的面积:\n{area}")
        x=i
cnt = contours[x]
cv2.imshow("binary",binary)
#寻找凸包并绘制凸包(轮廓)
hull = cv2.convexHull(cnt)
cv2.polylines(img,[hull],True,(0,255,0),2)
cv2.drawContours(img,contours,x,(0,0,255), 3)
# 显示图片
cv2.imshow('line', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

任务二 凸缺陷检测

案例二:凸缺陷

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()

任务三 轮廓常见特征值

案例一:宽高比

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()

案例二: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()

案例三:最大值和最小值及它们的位置

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()

案例四:平均颜色及平均灰度

meanVal = cv2.mean(o,mask = mask)  #mask是区域,所以必须是单通道的
print("meanVal=\n",meanVal)

任务四 实践:轮廓特征值的应用场景

案例:分类1

import cv2
import numpy as np
img = cv2.imread('face.png')  
cv2.imshow("original",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  
ret, binary = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)  
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)  
h,w,c=img.shape
mask = np.zeros((h,w,c),np.uint8)
for cnt in contours:
    
    x,y,w,h = cv2.boundingRect(cnt)
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),3)
    ratio = float(w)/h
    if ratio<1:
        cv2.drawContours(mask,[cnt],-1,(0,0,255), -1)
        #n+=1
        print(ratio,"是长的椭圆")
    else:
        cv2.drawContours(mask,[cnt],-1,(0,255,255), -1)
        #n+=1
        print(ratio,"是扁的椭圆")
cv2.imshow("result",mask)
cv2.waitKey()
cv2.destroyAllWindows()

案例:分类2

import cv2
import numpy as np
img = cv2.imread('face.png')  
cv2.imshow("original",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  
ret, binary = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)  
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)  
h,w,c=img.shape
mask = np.zeros((h,w,c),np.uint8)

for cnt in contours:
    
    x,y,w,h = cv2.boundingRect(cnt)
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),3)
    ratio = float(w)/h
    rectArea=w*h
    cntArea=cv2.contourArea(contours[0])
    extend=float(cntArea)/rectArea
    print(extend)
    
    if ratio<1:
        cv2.drawContours(mask,[cnt],-1,(0,0,255), -1)
        print(ratio,"是长的椭圆")
    else:
        cv2.drawContours(mask,[cnt],-1,(0,255,255), -1)
        print(ratio,"是扁的椭圆")
    if extend==0.9818696450428397:
        cv2.drawContours(mask,[cnt],-1,(255,0,255), -1)
        
cv2.imshow("result",mask)
cv2.waitKey()
cv2.destroyAllWindows()

我们下次见拜拜!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
轮廓拟合直线是指通过对图像中的轮廓进行拟合操作,得到与该轮廓相关联的直线。OpenCV提供了fitLine()函数来实现轮廓拟合直线的功能。该函数的参数包括输入的点集(轮廓点集),以及输出的直线。输出的直线可以使用cv::Vec4f类型(二维)或cv::Vec6f类型(三维)表示。输出的直线包含了直线的方向和一点,可以通过点斜式方程计算直线的斜率和截距。通过这些信息,我们可以得到一条完整的点斜式直线方程。具体的实现代码如下: ```cpp Vec4f oneline; fitLine(contours[i], oneline, DIST_L1, 0, 0.01, 0.01); float k, b; k = oneline / oneline - k * oneline`表示输入的轮廓点集,`oneline`表示输出的直线参数。通过计算直线的斜率和截距,我们可以得到一条完整的点斜式直线方程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [OpenCV4学习笔记(26)——轮廓拟合直线、寻找极值点、点多边形检测](https://blog.csdn.net/weixin_45224869/article/details/104888172)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [【OpenCV3】直线拟合——cv::fitLine()详解](https://blog.csdn.net/guduruyu/article/details/69505487)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值