I am new to opencv, start to learn it by extract char from simple captcha.
After some effort, I got findContours
and some method to clean the image, sometimes worked, but not more often.
use cv2.findContours
to get bounding boxes:
W
only cover a half, and not get b
.
from StringIO import StringIO
import string
from PIL import Image
import requests
import cv2
import numpy as np
import matplotlib.pyplot as plt
def get_ysdm_captcha():
url = 'http://www.ysdm.net/common/CleintCaptcha'
r = requests.get(url)
img = Image.open(StringIO(r.content))
return img
def scale_image(img, ratio):
return img.resize((int(img.width*ratio), int(img.height*ratio)))
def draw_rect(im):
im = np.array(im)
if len(im.shape) == 3 and im.shape[2] == 3:
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
else:
imgray = im
#plt.imshow(Image.fromarray(imgray), 'gray')
pilimg = Image.fromarray(imgray)
ret,thresh = cv2.threshold(imgray,127,255,0)
threimg = Image.fromarray(thresh)
plt.figure(figsize=(4,3))
plt.imshow(threimg, 'gray')
plt.xticks([]), plt.yticks([])
contours, hierarchy = cv2.findContours(np.array(thresh),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
areas = []
for c in contours:
rect = cv2.boundingRect(c)
area = cv2.contourArea(c)
areas.append(area)
x,y,w,h = rect
if area > 2000 or area < 200 : continue
cv2.rectangle(thresh,(x,y),(x+w,y+h),(0,255,0),1)
plt.figure(figsize=(1,1))
plt.imshow(threimg.crop((x,y,x+w,y+h)), 'gray')
plt.xticks([]), plt.yticks([])
plt.figure(figsize=(10,10))
plt.figure()
plt.imshow(Image.fromarray(thresh), 'gray')
plt.xticks([]), plt.yticks([])
image = get_ysdm_captcha()
im = scale_image(image, 3)
im = np.array(im)
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
imgray = cv2.GaussianBlur(imgray,(5,5),0)
# im = cv2.medianBlur(imgray,9)
# im = cv2.bilateralFilter(imgray,9,75,75)
draw_rect(imgray)
I tried my best to write above code. The solutions I imagine is:
cv2.findContours
I need 4
bounding boxes in some sizeNow I'm stuck , have no idea how to improve cv2.findContours
...
答案 0 :(得分:2)
您可以使用形态学操作来修改图像并填补空白,例如erode
和dilate
见这里: http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html
原件:
扩张型:
顺便说一句:我会在原始图像中实施HSV分离步骤,删除所有白色/灰色/黑色&#39;内容(低饱和度)。这将减少斑点的数量。在转换为灰度之前执行此操作。
最终结果:(之前添加了模糊步骤)
此外,如果总是有渐变,您可以检测到这种情况并滤除更多颜色。但是,如果您刚刚开始图像处理,那就有点多了;)
答案 1 :(得分:0)
findCountours在找到图像的所有连接组件时正常工作。例如,您的区域条件可能会避免您在字母b周围找到一个边界框。当然,如果你在每个连接的组件周围放置一个边界框,你将不会在每个角色周围放置一个边界框,因为你的字母中有很多洞。
如果你想分割字母,我会首先尝试使用开场操作(因为你的字母在白色背景上是黑色的,如果是相反的话它会关闭)以填补你的洞在你的信中。然后我会垂直投影像素并分析你得到的形状。如果您在此投影形状中找到谷点,您将获得字符之间的垂直限制。您可以水平地执行相同操作以获取字符的上限和下限。只有在文本是水平的情况下,此方法才有效。如果不是,您应该找到字符串的主轴角度,然后可以相应地旋转图像。要找到主轴角度,您可以在文本中插入椭圆并找到其主轴角度,或者您可以将图像旋转一定角度,直到您的水平投影达到最大值。