一、边缘检测

上一个博客中有讲到边缘检测中的sobel算子的方法

我们接着介绍其他方法

1.scharr算子和laplacion算子

这里我加上了sobel算计,进行对比

#sobel算子
import cv2
image1=cv2.imread(r"D:\project\123s.jpg")
image1_x_64=cv2.Sobel(image1,cv2.CV_64F,dx=1,dy=0)
image1_x_full=cv2.convertScaleAbs(image1_x_64)
image1_y_64=cv2.Sobel(image1,cv2.CV_64F,dx=0,dy=1)
image1_y_full=cv2.convertScaleAbs(image1_y_64)
image1_xy_Sobel_full=cv2.addWeighted(image1_x_full,1,image1_y_full,1,0)
cv2.imshow('image1_xy_Sobel_full',image1_xy_Sobel_full)

#scharr算子
# cv.scharr(src, ddepth, dx, dy[, dstl, scalel, deltal, borderType]]]])
#ddepth:输出图片的数据深度,由输入图像的深度进行选择
#dX:x轴方向导数的阶数
#dy:y轴方向导数的阶数
image2=cv2.imread(r"D:\project\123s.jpg",cv2.IMREAD_GRAYSCALE)#scharr算子
# image2=cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY)
#可以通过上面的方法变灰度图,也可以通过该方法,使用这个方法的时候要把第一句的cv2.IMREAD_GRAYSCALE删去
image2_x_64=cv2.Scharr(image2,cv2.CV_64F,dx=1,dy=0)
image2_x_full=cv2.convertScaleAbs(image2_x_64)
image2_y_64=cv2.Scharr(image2,cv2.CV_64F,dx=0,dy=1)
image2_y_full=cv2.convertScaleAbs(image2_y_64)
image2_xy_Scharr_full=cv2.addWeighted(image2_x_full,1,image2_y_full,1,0)
cv2.imshow('image2_xy_scharr_full',image2_xy_Scharr_full)

#laplacion算子
#ov2.Laplacian(src, ddepth[, dst[, ksize[, scale[, deltal, borderType]]]]])
#ddepth:输出图片的数据深度:
#ksize:计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
#scaLe:缩放比例因子,可选项,默认值为1
#delta:输出图像的偏移量,可选项,默认值为0
image3=cv2.imread(r"D:\project\123s.jpg",cv2.IMREAD_GRAYSCALE)
image3_lap=cv2.Laplacian(image3,cv2.CV_64F,ksize=1)#只能为奇数
image3_lap_full=cv2.convertScaleAbs(image3_lap)
cv2.imshow('image_lap_full',image3_lap_full)
cv2.waitKey(0)

左为sobel,中为scharr,右为laplacion,会发现scharr对边缘的检测会比较强,laplacion比较弱。

2.canny边缘检测

#canny边缘检测
# cv.canny( image, threshold1, threshold2l, aperturesize[, L2gradient]])
#image为输入图像。
#threshold1表示处理过程中的第一个阈值。fL
#threshold2表示处理过程中的第二个阈值。fH
import cv2
image4=cv2.imread(r"D:\project\123s.jpg",cv2.IMREAD_GRAYSCALE)
cv2.imshow('image4',image4)
image4_canny=cv2.Canny(image4,100,150)#低,高
cv2.imshow('image4_canny',image4_canny)
cv2.waitKey(0)

二、轮廓检测

查找轮廓的API:image, contours, hierarchy = cv2.findContours(img,mode,method)
参数:
img:需要实现轮廓检测的原图
mode:轮廓的检索模式,主要有四种方式:
CV2.RETR_EXTERNAL:只检测外轮廓,所有子轮廓被忽略
CV2.RETR_LIST:检测的轮廓不建立等级关系,所有轮廓属于同一等级
cv2.RETR_CCOMP:返回所有的轮廓,只建立两个等级的轮廓。一个对象的外轮廓为第1级组织结构。
而对象内部中空洞的轮廓为第2级组织结构,空洞中的任何对象的轮廓又是第1级组织结构。
Cv2.RETR_TREE:返回所有的轮廓,建立一个完整的组织结构的轮廓。
method:轮廓的近似方法,主要有以下两种:
  cv2.CHAIN_APPROX_NONE:存储所有的轮廓点。
  cv2.CHAIN_APPROX_SIMPLE:压缩模式,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。
返回:image:返回处理的原图
contours:包含图像中所有轮廓的List对象。其中每一个独立的轮廓信息以边界点坐标(x,y)的形式储存在numpy数组中。
hierarchy:轮廓的层次结构.一个包含4个值的数组:[Next,Previous,FirstChild,Parent]
Next:与当前轮廓处于同一层级的下一条轮廓
Previous:与当前轮廓处于同一层级的上一条轮廓
First Child:当前轮廓的第一条子轮廓
Parent:当前轮廓的父轮廓
注意:做轮廓检测前需要将图片读取为二值数据,即像素值只为0和255。
import cv2
image1=cv2.imread(r"D:\project\phone.png")
image1_gray=cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY)
cv2.imshow('image1_gray',image1_gray)
# cv2.waitKey(0)
ret,image1_binary=cv2.threshold(image1_gray,120,255,cv2.THRESH_BINARY)
cv2.imshow('image1_binary',image1_binary)
# cv2.waitKey(0)
_,contours,hierarchy=cv2.findContours(image1_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# contours=cv2.findContours(image1_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2]#不管opencv啥版本都能正常运行
# print(hierarchy)
print(len(contours))#检测到几个轮廓

三、轮廓绘制

cv2.drawContours(image, contours, contourIdx, color, thickness=None,lineType=None, hierarchy=None, maxLevel=None, offset=None)
参数含义如下:
image:要在其上绘制轮廓的输入图像。
contours:轮廓列表,通常由cv2.findContours()函数返回。
contourIdx:要绘制的轮廓的索引。如果为负数,则绘制所有轮廓。-1
color:轮廓的颜色,以B6R格式表示。例如,(0,255,0)表示绿色
thickness:轮廓线的粗细。默认值为1。
lineType:轮廓线的类型。默认值为cv2.LINE_8.
hierarchy:轮廓层次结构。通常由cv2.findContours()函数返回.
maxLevel:绘制的最大轮廓层级。默认值为None,表示绘制所有层级。
offset:轮廓点的偏移量。默认值为None

在上述轮廓检测后面加上

image_copy=image1.copy()
cv2.drawContours(image=image_copy,contours=contours,contourIdx=-1,color=(0,255,255),thickness=2)
#-1绘制所有轮廓,0为第0个,1是第1个,color是轮廓的颜色,轮廓的一个宽度
cv2.imshow('image_copy',image_copy)
cv2.waitKey(0)

四、轮廓面积,轮廓周长,轮廓外接圆,外接矩形

'''轮廓检测'''
import cv2
image1=cv2.imread(r"D:\project\phone.png")
image1_gray=cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY)
cv2.imshow('image1_gray',image1_gray)
# cv2.waitKey(0)
ret,image1_binary=cv2.threshold(image1_gray,120,255,cv2.THRESH_BINARY)
cv2.imshow('image1_binary',image1_binary)
# cv2.waitKey(0)
_,contours,hierarchy=cv2.findContours(image1_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# contours=cv2.findContours(image1_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2]#不管opencv啥版本都能正常运行
# print(hierarchy)
print(len(contours))

'''轮廓面积'''
# cv2.contourArea(contour[, oriented])  retval轮廓面积
#contour:顶点构成的二维向量组(如轮廓列表contours中的一个轮廓)
#oriented:定向区域标志,默认值为False,返回面积的绝对值,Ture时则根据轮廓方向返回带符号的数值
area_0 = cv2.contourArea(contours[0])#轮廓面积
print(area_0)
area_1 = cv2.contourArea(contours[1])
print(area_1)

'''轮廓周长'''
# arcLength(InputArray curve, bool closed)轮廓周长
#curve,输入的二维点集(轮廓顶点),可以是vector或Mat类型。
#closed,用于指示曲线是否封闭。
length = cv2.arcLength(contours[0],closed=True)
print(length)

'''根据面积显示特定轮廓'''
a_list=[]
for i in contours:
    if cv2.contourArea(i)>10000:
        a_list.append(i)
image1_copy = image1.copy()
image1_copy = cv2.drawContours(image=image1_copy, contours=a_list, contourIdx=-1,color=(0,255,0),thickness=3)
cv2.imshow( 'Contours_show_10000', image1_copy)
# cv2.waitKey(0)

'''轮廓定位好方法 根据轮廓面积进行排序'''
sortcnt = sorted(contours,key=cv2.contourArea,reverse=True)[0] #选取最大面积的轮廓
image_contours = cv2.drawContours(image1_copy, [sortcnt],contourIdx=-1,color=(0,0,255),thickness=3)
cv2.imshow( 'image_contours',image_contours)
# cv2.waitKey(0)

'''外接圆、外接矩形'''
cnt = contours[6]
(x,y),r= cv2.minEnclosingCircle(cnt)#计算轮廓的外接圆
image1_circle = cv2.circle(image1,(int(x),int(y)),int (r),(0,255,0),2)#绘制外接圆的方法
cv2.imshow( 'phone_circle',image1_circle)
# cv2.waitKey(0)

x,y,w,h= cv2.boundingRect(cnt)
image1_rectangle = cv2.rectangle(image1,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow( 'image1_rectangle',image1_rectangle)
cv2.waitKey(0)

五,轮廓近似

就是把复杂的轮廓用更少的点简化表示,用直线段代替曲线,变成多边形

#轮廓的近似
import cv2
# approx = cv2.approxPolyDP(curve, epsilon, closed)
#curve:输入轮廓。
#epsilon:近似精度,即两个轮廓之间最大的欧式距离。该参数越小,得到的近似结果越接近实际轮廓;反之,得到的近似结果会更川相略。
#closed:布尔类型的参数,表示是否封批轮院。如果是 True,表示输入轮康是封划的,近似结果也会是封闭的。
#返回值:approx:近似结果,是一个ndarray数组,为1个近似后的轮廓,包含了被近似出来的轮廓上的点的坐标

phone = cv2.imread(r"D:\project\phone.png")
phone_gray = cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY) #转换为灰/度图
ret,phone_thresh = cv2.threshold(phone_gray,120,255,cv2.THRESH_BINARY) #二值比

# image, contours, hierarchy = cV2.findContours (phone-thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX NONE)#获取轮廓
contours=cv2.findContours(phone_thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2]

epsilon = 0.01 * cv2.arcLength(contours[0],True)
approx = cv2.approxPolyDP(contours[0], epsilon,True)

print(contours[0].shape)
print(approx.shape)
phone_new = phone.copy()
image_contours = cv2.drawContours(phone_new, [approx],contourIdx=-1,color=(255,255,0),thickness=3)#
cv2.imshow( 'phone',phone)
cv2.waitKey(0)
cv2.imshow( 'image_contours',image_contours)
cv2.waitKey(0)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐