OpenCV中提取目标区域并标注(python)

前言

考核题
考核

一、blob分析

名词解释:计算机视觉中的Blob是指图像中的一块连通区域,Blob分析就是对前景/背景分离后的二值图像,进行连通域提取和标记。标记完成的每一个Blob都代表一个前景目标,然后就可以计算Blob的一些相关特征。
blob核心思想
搞清楚了这一点,就知道师兄给的这张图是在为我们减小难度
在这里插入图片描述
前景与后景的差别非常强烈
上代码

import cv2
import numpy as np
 
img = cv2.imread('zuobiao.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#读取并处理为单通道图片,为后续做准备
ret, binary = cv2.threshold(imgray, 127, 255, 0)#阈值处理
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)#查找检测物体的轮廓
for c in contours:
            (x, y, w, h) = cv2.boundingRect(c)
            img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 1)  
for i in range(len(contours)):
    mom = cv2.moments(contours[i])#计算中心矩
    pt = (int(mom['m10'] / mom['m00']), int(mom['m01'] / mom['m00']))  # 使用前三个矩m00, m01和m10计算重心
    cv2.circle(img, pt, 2, (0, 0, 255), 2)  # 画红点
    cv2.line(img, (x, y),((pt[0]),(pt[1])), (0, 0, 255),1)#画半径
    text = "(" + str(pt[0]) + ", " + str(pt[1]) + ")"#添加的文字
    cv2.putText(img, text, (pt[0]+10, pt[1]+10), cv2.FONT_HERSHEY_PLAIN, 1.5, (255, 255, 255), 2, 8, 0);#加坐标
    
print("--------- HL分析区域并标注的测试 ---------")    
cv2.imshow("center", img)
cv2.waitKey(0)
cv2.destroyAllWindows()         

太多库函数注释要写,放到代码里面会显得头重脚轻,索性单句拿出来一句句分析

首先运行以上代码
会发现这样一个错误
在这里插入图片描述
值错误:没有足够的值解包(应为3,得到2)
OpenCV4.0的说明文档中
在这里插入图片描述
我们只需把这句

contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

改为

image, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

即加上一个参数就好

先放效果图
效果
好的,下面将一些代码注释与用法总结如下

二、有关代码函数的注释与用法

1、cv2.threshold()阈值处理

imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#读取并处理为单通道图片,为后续做准备
ret, thresh = cv2.threshold(imgray, 127, 255, 0)#阈值处理

此语句的原型为

cv2.threshold (src, thresh, maxval, type)

Attention:
src:源图片必须是单通道
thresh:阈值,取值范围0~255
maxval:填充色,取值范围0~255
type:阈值类型,具体见下

阈值小于阈值的像素点大于阈值的像素点
0置0置填充色
1置填充色置0
2保持原色置灰色
3置0保持原色
4保持原色置0

因为要进行阈值处理,所以在前面一步需将我的彩色图片变为单通道,也就是灰色
为了深刻理解这个概念,运行是最直观的理解
代码如下:

import cv2

img = cv2.imread('pic.jpg',0)#预处理变为单通道图片
cv2.imshow('org',img)
# 运用二值化处理图片
retVal,img_after = cv2.threshold(img, 100 ,100, cv2.THRESH_BINARY)
cv2.imshow('org_retVal',img_after)

print("变化之前的图像是:\n",img)
print("变化之后的图像是:\n",img_after)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
可以看出,图像中像素大于100的全变成了100,这是因为阈值和填充色我选择了100,而小于100的应该变成0(由于这张图片没有小于100的…所以全为100…)
啊?你说无法说明?emmm那好吧,再来,观察数据,我选择设阈值为110
在这里插入图片描述
这里就能充分说明了,小于110的部分已经置为0了,而大于的部分呢,都变为了100。
在考核题的那串代码中,我将阈值设为127,也就是中间值,而填充色设为255,形成鲜明反差,有利于后续处理。

2、cv2.findContours()轮廓检测

image, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

python3这里返回三个值:image,contours,hierarchy

  1. image:一张二值图(binary),但不是灰度图像,应当是黑白图,只有0和1;
  2. contours:list结构,列表中每个元素代表一个边沿信息。每个元素是(x,1,2)的三维向量,x表示该条边沿里共有多少个像素点,第三维的那个“2”表示每个点的横、纵坐标;
  3. hierarchy:返回类型是(x,4)的二维ndarray。x和contours里的x是一样的意思。如果输入选择cv2.RETR_TREE,则以树形结构组织输出,hierarchy的四列分别对应下一个轮廓编号、上一个轮廓编号、父轮廓编号、子轮廓编号,该值为负数表示没有对应项;

括号中的参数我绘制了一个表格如下表:

cv2.RETR_EXTERNAL只检测外轮廓
cv2.RETR_LIST只检测外轮廓
cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。(如果内孔内还有一个连通物体,这个物体的边界也在顶层)
cv2.RETR_TREE建立一个等级树结构的轮廓

简单试试这个函数

import cv2
 
img = cv2.imread('pic.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv2.imshow("img", binary)
image,contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,contours,-1,(0,0,225),1)
print("--------- HL边缘检测的测试 ---------")
cv2.imshow("binary", binary)
cv2.waitKey(0)

在这里插入图片描述

3、cv2.boundingRect©矩形边框

(x, y, w, h) = cv2.boundingRect(c)

矩形边框(Bounding Rectangle)是用一个最小的矩形,把找到的形状包起来。
在cv2.boundingRect(cnt)这个函数中

  • cnt是一个轮廓点集合,也就是它的参数,可以通过cv2.findContours获取;
  • 返回四个值,分别是x,y,w,h;
  • x,y是矩阵左上点的坐标;
  • w,h是矩阵的宽和高;
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 1)

函数原型:cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[,
shift]]])

  • img:要画的圆所在的矩形或图像
  • pt1:矩形左上角的点
  • pt2:矩形右下角的点
  • color:线条颜色,如 (0, 255, 255) 黄色,BGR
  • thickness:线条宽度
  • lineType:8 (or omitted) : 8-connected line 4:4-connected line CV_AA - antialiased line
  • shift:坐标点小数点位数

4、cv2.moments()图像的矩

参数如下:
图像的矩可以帮助我们计算图像的质心,面积等
M = cv2.moments(cnt)
根据这些矩的值,我们可以计算出对象的重心:
cx = int(M[‘m10’]/M[‘m00’])
cy = int(M[‘m01’]/M[‘m00’])

pt = (int(mom['m10'] / mom['m00']), int(mom['m01'] / mom['m00']))  # 使用前三个矩m00, m01和m10计算重心

5、cv2.circle()画圆心

函数原型:cv2.circle(img, center, radius, color[, thickness[, lineType[,
shift]]])

作用就是根据给定的圆心和半径等画圆

  • img:输入的图片data
  • center:圆心位置
  • radius:圆的半径
  • color:圆的颜色
  • thickness:圆形轮廓的粗细(如果为正)。负厚度表示要绘制实心圆
  • lineType: 圆边界的类型。
  • shift:中心坐标和半径值中的小数位数。
cv2.circle(img, pt, 2, (0, 0, 255), 2) 

画红点啦当然通道应为(0,0,255)红色,过年就要喜气~

6、 cv2.line()画直线

 cv2.line(img, (x, y),((pt[0]),(pt[1])), (0, 0, 255),1)

这个是我自作主张加上去的…

函数原型:img=cv.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])

用途:给定一个图像img,连接点pt1和pt2的坐标,在图中画一条直线,color表明线的颜色,thickness是线条粗细
所以我的起点是前面刚画好的圆心,终点是边框的一个点,用红色线连接,细细的一根。

7、cv2.putText()写文字

text = "(" + str(pt[0]) + ", " + str(pt[1]) + ")"
    cv2.putText(img, text, (pt[0]+10, pt[1]+10), cv2.FONT_HERSHEY_PLAIN, 1.5, (255, 255, 255), 2, 8, 0);

因为数值未知,所以用了text来引用,再放到该函数里表示。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值