首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

计算机视觉(四):请从图像中分割出珍珠,并检测其边缘

Project 4:

请从图像中分割出珍珠,并检测其边缘

打开珍珠图像的原图。

待解决的问题:

图像中的珍珠大小不一,有部分重叠,并且还有很多反射的光斑,还有珍珠挡住了光以后形成的阴影部分影响检测。我要做到的是准确的检测分割出珍珠,并且准确的检测出珍珠形状的边缘。

思路及原理:

具体思路步骤如下:l

1.先将图片转化为灰度图,cv2.cvtColor(input_image, flag)函数实现图片颜色空间的转换,flag 参数决定变换类型。如 BGR->Gray flag 就可以设置为cv2.COLOR_BGR2GRAY。

2.得到灰度图以后,采用cv2.HoughCircles函数来检测珍珠的形状,并在原图上画出圆,圈出珍珠,完成检测。

cv2.HoughCircles(image, method, dp, minDist, circles, param1, param2, minRadius, maxRadius) image为输入图像,要求是灰度图像,circles1为输出圆向量,每个向量包括三个浮点型的元素——圆心横坐标,圆心纵坐标和圆半径。method为使用霍夫变换圆检测的算法,它的参数是CV_HOUGH_GRADIENT

dp为第一阶段所使用的霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推

minDist为圆心之间的最小距离,如果检测到的两个圆心之间距离小于该值,则认为它们是同一个圆心

param1为边缘检测时使用Canny算子的高阈值

param2为边缘检测时使用Canny算子的低阈值

minRadius和maxRadius为所检测到的圆半径的最小值和最大值

3.对原图像进行高斯滤波去除图像中的噪声,然后采用Canny边缘检测的方法检测图像中珍珠的边缘。

Canny 边缘检测是一种非常流行的边缘检测算法,由于边缘检测很容易受到噪声影响,所以第一步是采用3*3的高斯滤波器滤掉噪声。

OpenCV中只需要一个函数:cv2.Canny(),就可以完成以上几步。让我们看如何使用这个函数。这个函数的第一个参数是输入图像。第二和第三个分别是minVal和maxVal。

其中较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来。可选参数中apertureSize就是Sobel算子的大小。而L2gradient参数是一个布尔值,如果为真,则使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开方),否则使用L1范数(直接将两个方向导数的绝对值相加)。

现在要确定那些边界才是真正的边界。这时我们需要设置两个阈值:minVal和maxVal。当图像的灰度梯度高于maxVal时被认为是真的边界,那些低于minVal的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。如下所示:

A高于阈值maxVal所以是真正的边界点,C虽然低于maxVal但高于minVal并且与A相连,所以也被认为是真正的边界点。而B就会被抛弃,因为它不仅低于maxVal而且不与真正的边界点相连。所以选择合适的maxVal和minVal对于能否得到好的结果非常重要。在这一步一些小的噪声点也会被除去,因为我们假设边界都是一些长的线段。

编程实现:

我依然采用Python+OpenCV的工具来完成这个项目

首先是读取原图片,并定义一个函数用来显示图片,方便在后面调用。并得到该图像的大小。

接下来对图像进行灰度图处理

然后调用cv2.HoughCircles来完成对珍珠的检测,并得到珍珠所在位置的中心坐标,以及珍珠的半径,调节相关阈值,以圆心半径画出圆,准确的圈出图中的珍珠。

接下来完成对图像边缘的检测,先进行高斯滤波,采用3*3,标准差为1的高斯滤波器。

滤波以后采用Canny边缘检测算法,检测边缘

L2gradient参数是一个布尔值,使他为真,使用更精确的L2范数进行计算,得到的结果更加准确。

最后使想要看到的图像显示出来。

结果及分析:

在这里我还对灰度图进行二值化,以及对原图进行了直方图均衡化,期望从不同角度来探究检测和分割的效果。

图像中输入的原图。接下来是经过转化以后得到的灰度图。

对灰度图进行二值化处理以后得到:

得到灰度图像的直方图

然后是均衡化以后的直方图

对灰度图进行均衡化处理以后的图像

接下来是采用了Canny边缘检测的方法检测珍珠的边缘,经过高斯滤波以后的边缘检测除去了很多杂七杂八的线条,使边缘更加简洁明朗,清晰可见。

接下来看一下高斯圆检测方法得到的10个珍珠的圆心坐标和半径大小的矩阵。

采用这些数据进行画圆,将珍珠准确地从图中分割出来。

可以看到图中珍珠检测以及边缘分割的效果非常好,符合项目预期要求。

结论:

从结果图中可以明显看出,canny算子连珍珠的倒影边缘和珍珠表面的反光部分的边缘都检测出来了,干扰的线条很少,简洁清晰明了。而对珍珠的检测,效果非常理想,每一颗珍珠都被清晰地检测了出来,用圆沿着珍珠的边缘准确的勾勒出了线条。达到了项目预期的目标。

附上所有程序代码:

#coding=utf-8

import cv2

import numpy as np

import matplotlib.pyplot as plt

#定义一个用来显示图片的的函数

def readPic(name1,name2):

cv2.namedWindow(name1, flags=0)

cv2.resizeWindow(name1, 500, 500)

cv2.imshow(name1,name2)

#读取图片

img = cv2.imread("C:/Users/ASUS/8/pearls.jpg",1)

print(np.shape(img)) #425*580*3

#对图像进行高斯模糊

img2 = cv2.GaussianBlur(img,(3,3),1)

#print(img)

#对图像进行灰度图处理

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#绘制灰度直方图

hist1 = cv2.calcHist([img],[0],None,[256],[0,256])

plt.figure()#新建一个图像

plt.title("Grayscale Histogram")#图像的标题

plt.xlabel("Bins")#X轴标签

plt.ylabel("# of Pixels")#Y轴标签

plt.plot(hist1)#画图

plt.xlim([0,256])#设置x坐标轴范围

#对直方图进行均衡化

equ = cv2.equalizeHist(gray)

#绘制灰度均衡化以后的直方图

hist2 = cv2.calcHist([equ],[0],None,[256],[0,256])

plt.figure()#新建一个图像

plt.title("Grayscale Histogram")#图像的标题

plt.xlabel("Bins")#X轴标签

plt.ylabel("# of Pixels")#Y轴标签

plt.plot(hist2)#画图

plt.xlim([0,256])#设置x坐标轴范围

#对图像进行二值化处理

ret,img1 = cv2.threshold(gray,200,255,cv2.THRESH_BINARY)

#对图像进行检测边缘

edges1 = cv2.Canny(img2, 10, 80, apertureSize = 3,L2gradient=True)

#edges2 = cv2.Canny(img, 10, 80, apertureSize = 3)

circles1 = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,

55,param1=100,param2=25,minRadius=20,maxRadius=60)

print(circles1)

circles = circles1[0,:,:]#提取为二维

print(circles)

circles = np.uint16(np.around(circles))#四舍五入,取整

for i in circles[:]:

cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),2)#画圆

cv2.circle(img,(i[0],i[1]),2,(255,0,255),5)#画圆心

#显示直方图均衡化图

readPic('equ',equ)

#显示二值图

readPic('img1',img1)

#显示灰度图

readPic('gray',gray)

#显示检测图

readPic('img',img)

#显示边缘检测图1

readPic('edges1',edges1)

#显示边缘检测图2

#('edges2',edges2)

plt.show()#显示图像

cv2.waitKey()

cv2.destroyAllWindows()

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180211G0FA0I00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券