如何解决Python 数字识别彩色屏幕
我使用python搜索图像识别。似乎没有关于从彩色背景中提取数字的教程,所以我跟着 THIS TUTORIAL
import cv2
import matplotlib.pyplot as plt
def detect_edge(image):
''' function Detecting Edges '''
image_with_edges = cv2.Canny(image,100,200)
images = [image,image_with_edges]
location = [121,122]
for loc,img in zip(location,images):
plt.subplot(loc)
plt.imshow(img,cmap='gray')
plt.savefig('edge.png')
plt.show()
image = cv2.imread('myscreenshot.png',0)
detect_edge(image)
这是我的图片:
结果如下:
有什么办法可以打印出这些数字?
解决方法
这里有一些代码可以让这张图片的边缘干净利落。
import cv2
import numpy as np
# load image
img = cv2.imread("numbers.png");
# change to hue colorspace
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV);
h,s,v = cv2.split(hsv);
# use clahe to improve contrast
# (the contrast is pretty good already,so not much change,but good habit to have here)
clahe = cv2.createCLAHE(clipLimit = 10)
contrast = clahe.apply(v);
# use canny
canny = cv2.Canny(contrast,20,110);
# show
cv2.imshow('i',img);
cv2.imshow('v',v);
cv2.imshow('c',contrast);
cv2.imshow("canny",canny);
cv2.waitKey(0);
# save
cv2.imwrite("edges.png",canny);
不使用任何 OCR(如 pytesseract 或其他东西),我看不出有什么明显的方法可以始终如一地将此图像转换为“文本”数字。我会把它留给其他人,他们可能知道如何在没有任何模式识别的情况下解决这个问题,因为没有它我什至不知道从哪里开始。如果您愿意放弃该限制,那么 pytessaract 应该没有问题;甚至可能不做这样的处理。
好的,我填写了图片的数字。 OpenCV 的 findContours 的层次结构由于某种原因没有合作,所以我不得不手动执行它,这使得这段代码非常笨拙。老实说,如果我要从头开始再试一次,我会尝试找到有助于少量总像素和每个阈值的颜色,然后组合蒙版。
import cv2
import numpy as np
# check if small box is in big box
def contained(big,small):
# big corners
x,y,w,h = big;
big_tl = [x,y];
big_br = [x+w,y+h];
# small corners
x,h = small;
small_tl = [x,y];
small_br = [x+w,y+h];
# check
if small_tl[0] > big_tl[0] and small_br[0] < big_br[0]:
if small_tl[1] > big_tl[1] and small_br[1] < big_br[1]:
return True;
return False;
# load image
img = cv2.imread("numbers.png");
# change to hue colorspace
hsv = cv2.cvtColor(img,but good habit to have here)
clahe = cv2.createCLAHE(clipLimit = 10)
contrast = clahe.apply(v);
# rescale
scale = 2.0;
h,w = img.shape[:2];
h = int(h * scale);
w = int(w * scale);
contrast = cv2.resize(contrast,(w,h),cv2.INTER_LINEAR);
img = cv2.resize(img,cv2.INTER_LINEAR);
# use canny
canny = cv2.Canny(contrast,10,60);
# show
cv2.imshow('i',canny);
cv2.waitKey(0);
# try to fill in contours
# contours
_,contours,hierarchy = cv2.findContours(canny,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE);
# filter contours by size
# filter out noisy bits and the big grid boxes
filtered = [];
for contour in contours:
perimeter = cv2.arcLength(contour,True);
if 50 < perimeter and perimeter < 750:
filtered.append(contour);
# draw contours again
# create a mask of the contoured image
mask = np.zeros_like(contrast);
mask = cv2.drawContours(mask,filtered,-1,255,-1);
# close to get rid of annoying little gaps
kernel = np.ones((3,3),np.uint8)
mask = cv2.dilate(mask,kernel,iterations = 1);
mask = cv2.erode(mask,iterations = 1);
# contours
_,hierarchy = cv2.findContours(mask,cv2.CHAIN_APPROX_NONE);
# alright,hierarchy is being stupid,plan B
# SUUUUUPEEERRR JAAAANK
outer_cntrs = [a for a in range(len(contours))];
children = [];
for a in range(len(contours)):
if a in outer_cntrs:
# get current box
big_box = cv2.boundingRect(contours[a]);
# check against all other boxes
for b in range(0,len(contours)):
if b in outer_cntrs:
small_box = cv2.boundingRect(contours[b]);
# remove any children
if contained(big_box,small_box):
outer_cntrs.remove(b);
children.append(contours[b]);
# # select by hierarchy
top_cntrs = [];
for a in range(len(contours)):
if a in outer_cntrs:
top_cntrs.append(contours[a]);
# create a mask of the contoured image
mask = np.zeros_like(contrast);
mask = cv2.drawContours(mask,top_cntrs,-1);
mask = cv2.drawContours(mask,children,-1);
# close
kernel = np.ones((3,iterations = 1);
# do contours agains because opencv is being super difficult
# honestly,at this point,a fill method would've been better
# contours
_,cv2.CHAIN_APPROX_NONE);
# fill in
for con in contours:
cv2.fillPoly(mask,pts = [con],color=(255));
for con in children:
cv2.fillPoly(mask,color=(0));
# resize back down
h,w = mask.shape;
h = int(h / scale);
w = int(w / scale);
mask = cv2.resize(mask,h));
# show
cv2.imshow("mask",mask);
cv2.waitKey(0);
# save
cv2.imwrite("filled.png",mask);
,
您可以分三步找到数字
-
- 应用erosion
-
- 使用 pytesseract 读取
-
自适应阈值结果:
-
侵蚀结果:
-
Pytesseract 结果:
-
8 | 1 5 9 4 @ 3 | 3 6 | 1
-
有多种页面分割模式可用于 pytesseract
-
如果您想从输出中删除
|
,您可以使用 re.sub -
text = re.sub('[^A-Za-z0-9]+',',text)
-
结果将是:
-
8 1 5 9 4 3 3 6 1
-
-
代码:
import cv2
import pytesseract
import re
import numpy as np
image = cv2.imread("7UUGYHw.png")
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,13,2)
erode = cv2.erode(thresh,np.array((7,7)),iterations=1)
text = pytesseract.image_to_string(erode,config="--psm 6")
text = re.sub('[^A-Za-z0-9]+','\n',text)
print(text)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。