Tayyab Vohra
Tayyab Vohra

Reputation: 1672

How to sharpen the edges in opencv python

I am learning image processing in which I am trying to sharpen the edges of the images using opencv in python , i have reduced the noise as much as i could but now i want to make the edges of the image more clear , i have tried cv2.Canny() but it didn't work out as much.

this is the image

enter image description here

After applying c2.Canny()

enter image description here

but I am trying to more sharp the words border or edges

this is my code

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)

Upvotes: 5

Views: 20553

Answers (3)

Shravya Boggarapu
Shravya Boggarapu

Reputation: 592

I looked the accepted answer and felt that it is good process but a lot of steps are not needed. Such as, Canny adds no value in a binary image. It is a complex process meant to detect sharp edges in images which have soft gradient. Sobel/Laplacian would give the same result as Canny for a binary image.

Also, this is not exactly sharpening of edges, more like refining.

My steps would be as follows:

  1. Threshold to binarize image

  2. Apply erode and dilate individually because then you have more control over things like in-place or not, memory management if you write in C/C++. This matters when you have more than one iteration, to handle more noise.

  3. Find contours. Based on use case, if you don't have loops (such as the loop in letter P), you can use find the only the external contours to optimise the code.

  4. Iterate through the contours and remove any contour below threshold from the list of contours.

  5. You already have the entire edge in the form of list of points here. If you can, use the edges as is or just create a blank image and draw all the valid contours with thickness 1 (only edges)

     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)
    

Upvotes: 1

fmw42
fmw42

Reputation: 53182

Here is one way to handle that in Python/OpenCV.

  • Read the input as grayscale
  • Threshold it to be sure it is binary
  • Apply morphology close
  • Find contours and removal all small areas in the input by drawing black over them
  • Apply Canny edge detection
  • Save the results

Input:

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)


Thresholded image:

enter image description here

Morphology Open applied:

enter image description here

Small areas removed:

enter image description here

Canny edges:

enter image description here

Upvotes: 7

ahmadgh74
ahmadgh74

Reputation: 821

First remove the image noise with Gaussian blur and use auto threshold canny like following code :

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)

i hope this helps to you

Upvotes: 1

Related Questions