Reputation: 1672
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
After applying c2.Canny()
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
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:
Threshold to binarize image
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.
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.
Iterate through the contours and remove any contour below threshold from the list of contours.
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
Reputation: 53182
Here is one way to handle that in Python/OpenCV.
Input:
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:
Morphology Open applied:
Small areas removed:
Canny edges:
Upvotes: 7
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