9
$\begingroup$

I want to process different type of image to extract actual text from noisy image .I am using open cv to do this job it is working fine but the problem is I need to set different lower threshold to convert noisy image to readable text.Is it possible to set single threshold which removes noise from all images by doing some pre processing ?

Main goal : I am trying to remove that wavy horizontal line and make the character clear to read

Code used:

import cv2

# Load an color image in grayscale
img = cv2.imread('it_captcha3.jpg',0)
ret, thresh_img = cv2.threshold(img, 180, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('grey image',thresh_img)
cv2.imwrite("result11.jpg", thresh_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Captcha1 :

enter image description here

Processed image : threshold used -> low: 180 high ->255,

enter image description here

CAPTCHA : 2

enter image description here

PROCESSED IMAGE: threshold used -> low: 200 high ->255

enter image description here

captcha : 3

enter image description here

processed : low -> 165 high : 255

enter image description here

$\endgroup$
1

3 Answers 3

4
$\begingroup$

first of all remember that there is no single solution for all kind of noise and all kind of images. that being said i can think of two solution. first is using Otsu thresholding:

ret,thresh_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)

this will try to guess a good threshold for the image being used.

the other solution would be using "close" morphology transform after thresholding. it will first dilate and then erode the image and using a good kernel( it is also called structuring element ) you can remove the line(although you may remove some of the useful pixels too!!)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4,8))
morph_img = cv2.morphologyEx(thresh_img, cv2.MORPH_CLOSE, kernel)

enter image description here

above is the result of using both otsu threshold and morphology close

$\endgroup$
3
$\begingroup$

You might be able to take these steps:

  1. Use Otsu threshold cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU) to get the image in only pure white and pure black. (Thanks @HKoshdel point it out)
  2. Use Hough Transformation to find the curve lines in your image. (OpenCV only has the Hough transform for straight lines, you can write your own one for detecting curves. http://en.wikipedia.org/wiki/Generalised_Hough_transform )
  3. Filter out the curve lines that are shorter or equal to one letter width
  4. Now go through the curve lines pixel by pixel left to right and delete it when it is thin (when only have a little number of same colour pixels above and below) and keep it when it is thick (when it interrupts words)

At the end, this way should be able to return you with an image with no curves and have all the complete letters

$\endgroup$
1
$\begingroup$

It might be interesting to test your idea in the opencv-flow ide. It seems to me that your code can be structured in this visual tool and see the results in real time.

Link: https://opencvflow.org/

There you can test different types of thresholds.

$\endgroup$
1
  • $\begingroup$ Thank you Rafael, this helped out a lot. Such an amazing resource, and it's quite underrated. $\endgroup$ Dec 28, 2022 at 19:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.