如何在opencv python中锐化边缘

时间:2020-03-27 21:52:22

标签: python python-3.x opencv image-processing

我正在学习图像处理,在其中尝试使用python中的opencv锐化图像的边缘,我已尽我所能降低了噪点,但现在我想使图像的边缘更清晰,我尝试过cv2.Canny(),但效果不佳。

这是图片

enter image description here

应用c2.Canny()

enter image description here

但是我想使边界或边缘一词更清晰

这是我的代码

import cv2
import matplotlib.pyplot as plt
img_1 = cv2.imread('noise/1.png',cv2.IMREAD_GRAYSCALE)
edges = cv2.Canny(img_1,200,200)
plt.imshow(edges)

3 个答案:

答案 0 :(得分:3)

这是在Python / OpenCV中处理该问题的一种方法。

  • 将输入读取为灰度
  • 将其阈值确定为二进制
  • 应用形态学关闭
  • 查找轮廓并通过在其上绘制黑色来去除输入中的所有小区域
  • 应用Canny边缘检测
  • 保存结果

输入:

enter image description here

import cv2
import numpy as np

# read image as grayscale
img = cv2.imread('K.png', cv2.IMREAD_GRAYSCALE)

# threshold to binary
thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY)[1]

# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# find contours - write black over all small contours
letter = morph.copy()
cntrs = cv2.findContours(morph, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
for c in cntrs:
    area = cv2.contourArea(c)
    if area < 100:
        cv2.drawContours(letter,[c],0,(0,0,0),-1)

# do canny edge detection
edges = cv2.Canny(letter, 200, 200)

# write results
cv2.imwrite("K_thresh.png", thresh)
cv2.imwrite("K_morph.png", morph)
cv2.imwrite("K_letter.png", letter)
cv2.imwrite("K_edges.png", edges)

# show results
cv2.imshow("K_thresh", thresh)
cv2.imshow("K_morph", morph)
cv2.imshow("K_letter", letter)
cv2.imshow("K_edges", edges)
cv2.waitKey(0)


阈值图片:

enter image description here

应用形态开放:

enter image description here

小区域已删除:

enter image description here

Canny边缘:

enter image description here

答案 1 :(得分:1)

首先使用Gaussian blur消除图像噪音,然后使用自动阈值标准,如以下代码所示:

def auto_canny(image, sigma=0.33):
    v = np.median(image)
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0 + sigma) * v))
    edged = cv2.Canny(image, lower, upper)
    return edged

def main():
    img_1 = cv2.imread('noise/1.png',cv2.IMREAD_GRAYSCALE)
    blurred = cv2.GaussianBlur(img_1, (3, 3), 0)
    auto_edge = auto_canny(blurred)
    plt.imshow(auto_edge)

我希望这对您有帮助

答案 2 :(得分:1)

我看了接受的答案,觉得这是一个很好的过程,但不需要很多步骤。例如,Canny 在二值图像中不添加任何值。这是一个复杂的过程,旨在检测具有软梯度的图像中的锐利边缘。对于二值图像,Sobel/Laplacian 将给出与 Canny 相同的结果。

此外,这并不完全是锐化边缘,更像是精炼。

我的步骤如下:

  1. 图像二值化阈值

  2. 单独应用 erode 和 dilate,因为如果您用 C/C++ 编写,那么您可以更好地控制诸如就地与否、内存管理之类的事情。当您进行多次迭代以处理更多噪音时,这一点很重要。

  3. 寻找轮廓。 根据用例,如果你没有循环(比如字母 P 中的循环),你可以使用 find the only external轮廓来优化代码。

  4. 遍历轮廓并从轮廓列表中删除任何低于阈值的轮廓。

  5. 您已经在此处以点列表的形式获得了整个边缘。如果可以,按原样使用边缘或仅创建一个空白图像并绘制厚度为 1(仅边缘)的所有有效轮廓

     import cv2
     import numpy as np
    
     # read image as grayscale
     img = cv2.imread('K.png', cv2.IMREAD_GRAYSCALE)
    
     # threshold to binary
     thresh = cv2.threshold(img, 1, 255, cv2.THRESH_BINARY)[1]
    
     # apply morphology.
     kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
     morph = cv2.erode(thresh, kernel)
     morph = cv2.dilate(morph, kernel)
    
     # find contours & draw only valid contour edges on a black image
     letter = np.zeros_like(img)
     cntrs, hier = cv2.findContours(morph, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
     for idx, c in enumerate(cntrs):
         area = cv2.contourArea(c)
         if area > 100:
             cv2.drawContours(letter, cntrs, idx, 255, 1, 8, hier)
    
     # write results
     cv2.imwrite("K_thresh.png", thresh)
     cv2.imwrite("K_morph.png", morph)
     cv2.imwrite("K_letter.png", letter)
    
     # show results
     cv2.imshow("K_thresh", thresh)
     cv2.imshow("K_morph", morph)
     cv2.imshow("K_letter", letter)
     cv2.waitKey(0)