OpenCV-python学习笔记(六)——梯度算子,边缘检测和轮廓提取

文章目录

  • gradients and edge detection梯度和边缘检测
    • 1 laplacian拉普拉斯算子
    • 2 sobel算子
    • 3 canny edge detector边缘探测
  • contours轮廓
    • 1 counting coins数硬币
    • 2 crop coins裁切提取硬币

gradients and edge detection梯度和边缘检测

边缘检测,就是用数学方法找出一幅图像中像素值突变的点。

第一件事,就是找出灰度图像中的梯度,在x方向和y方向中找出可能有边缘的区域。

接着我们会使用canny边缘检测,包括图像降噪,找到图像梯度(利用在水平和竖直方向上的sobel核),非最大值抑制non-maximum suppresion,和滞后阈值hysteresis thresholding。

1 laplacian拉普拉斯算子

# 注意从黑向白映射是一个正的斜坡函数,但从白向黑映射是一个负的斜坡函数
# 所以需要用cv2.CV_64F这种格式
lap = cv2.Laplacian(image, cv2.CV_64F)
lap = cp.uint8(np.absolute(lap))
cv2.imshow("Laplacian", lap)

OpenCV-python学习笔记(六)——梯度算子,边缘检测和轮廓提取_第1张图片

2 sobel算子

# 水平梯度
sobelX = cv2.Sobel(image, cv2.CV_64F, 1, 0)
sobelX = np.uint8(np.absolute(sobelX))
cv2.imshow("Sobel X", sobelX)
# 垂直梯度
sobelY = cv2.Sobel(image, cv2.CV_64F, 0, 1)
sobelY = np.uint8(np.absolute(sobelY))
cv2.imshow("Sobel Y", sobelY)
# 结合x和y两个方向的梯度
sobelCombined = cv2.bitwise_or(sobelX,sobelY)
cv2.imshow("Sobel Combined", sobelCombined)

OpenCV-python学习笔记(六)——梯度算子,边缘检测和轮廓提取_第2张图片

3 canny edge detector边缘探测

canny边缘探测是一个多步骤的过程,涉及到滤波降噪,计算sobel在两个方向上的梯度,边缘抑制suppressing edeges,和滞后阈值hysteresis thresholding,最终决定一个像素是否像是个边缘。

# 所有的梯度和边缘探测算子都需要转换成灰度图
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 仅canny需要使用模糊
image = cv2.GaussianBlur(image, (5,5), 0)
# 使用canny算子
# 第一个阈值表示低于30的梯度将不会被判定成边缘
# 第二个阈值表示超过150的梯度才会被判定成边缘
canny = cv2.Canny(image, 30, 150)

OpenCV-python学习笔记(六)——梯度算子,边缘检测和轮廓提取_第3张图片

contours轮廓

轮廓是一条曲线上的点,并且这条曲线没有间断。

怎样找到图像的轮廓呢,首先要获得二值化图像,无论是使用边缘检测还是二值化。接下来是一个使用canny边缘检测算子来找出硬币的轮廓,然后找到实际硬币的轮廓的例子。

1 counting coins数硬币

# 基础处理,二值化,模糊,探测边缘
gray = cv2.cvtColor()
blurred = cv2.GaussianBlur()
edged = cv2.Canny(blurred, 30, 150)
cv2.imshow("Edges", edged)

# 第二个参数表示返回外围最大轮廓,如果使用cv2.RETR_LIST可以返回所有轮廓
# 第三个参数表示分层架构,还可以使用cv2.RETR_COMP和cv2.RETR_TREE
(_, cnts, _) = cv2.findCoutours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print("{} coins in this image".format(len(cnts)))

coins = image.copy()
# 参数分别表示画布,轮廓,轮廓序号(-1代表全部),颜色,线条宽度
cv2.drawCountours(coins, cnts, -1, (0,255,0), 2)
cv2.imshow("coins", coins)

OpenCV-python学习笔记(六)——梯度算子,边缘检测和轮廓提取_第4张图片

2 crop coins裁切提取硬币

for (i,c) in enumerate(cnts):
    # 裁切出一块长方形区域,用来放圆形
    (x,y,w,h) = cv2.boundingRect(c)
    print("coin #{}".format(i+1))
    coin = image[y:y+h, x:x+w]
    cv2.imshow("Coin", coin)
    
    # 新建一块大的画布 
    mask = np.zeros(image.shape[:2], dtype = "uint8")
    # 找出轮廓圆的圆心和半径
    # 输入为轮廓,输出为圆心和半径
    ((centerX,centerY),radius) = cv2.minEnclosingCircle(c)
    # 画出圆,这些圆本质上是一个白色蒙版,mask成为一个遮罩
    cv2.circle(mask,(int(centerX), int(centerY)), int(radius), 255, -1)
    # 把mask缩小到和coin一样大的长方形区域
    mask = mask[y:y+h, x:x+w]
    cv2.imshow("Masked Coin", cv2.bitwise_and(coin,coin,mask = mask))
    

OpenCV-python学习笔记(六)——梯度算子,边缘检测和轮廓提取_第5张图片

你可能感兴趣的:(OpenCV,opencv,python,图像处理)