解决方案
1、图片处理
先设定好一个方便处理的像素,再对图片进行处理。
if isHorrizontal:
img = cv2.resize(img, (int(size/height*width), size))
else:
img = cv2.resize(img, (size, int(size/width*height)))
高斯模糊、自适应阈值化处理、对二值化图像进行腐蚀膨胀去除噪点。
为了防止因图片主体太小而找不到,先将图片裁剪,找到包含图片在内的最大矩形。
def maxBorder(img):
def ImgCut(img):
1、霍夫直线,找图片边框
lines = cv2.HoughLines(img_hough, 1, np.pi / 180, int(imgAverageSize/2))
对于占据整个图片超过一半的图像视为图片的主体也就是数独,然后画出霍夫直线,并将直线方程都保存在lines里面。
将霍夫直线的交点找出并画出,限制所描的点在数独内部,最后merge只剩下比较规则的交点,并将交点坐标保存在points里面。
for i in range(len(lines)):
for j in range(i+1, len(lines)):
p = ItsPoint(lines[i], lines[j])
x = p[0]
y = p[1]
if x >= 0 and x < width and y >= 0 and y < height and img_box[int(p[1]), (p[0])] != 0:
points.append((int(x), int(y)))
cv2.circle(img_bodPt, (int(p[0]), int(p[1])),
3, (0, 0, 255), -1)
2、寻找最大面积法确定四边形四个顶点
已经知道包括定点在内的所有点坐标,所以只要找到所有点能围成面积最大的四个点就是顶点。
找到四个顶点在画出经过这四个点的霍夫直线,这样就找到了四边形的边界。
即使数独图片在照片中被歪曲成了梯形,也能根据最大的面积找出最外界的边框。
最后裁剪出所需要的矩形。
maxSpace = 0
for i in range(len(points)):
for j in range(i+1, len(points)):
dp1 = points[i]
dp2 = points[j]
ddp = deta(dp2, dp1)
p1 = (-1, -1)
maxS1 = 0
for p in points:
if cross(ddp, deta(p, dp1)) > 0:
s1 = 1/2*abs(cross(ddp, deta(p, dp1)))
if s1 > maxS1:
maxS1 = s1
p1 = p
p2 = (-1, -1)
maxS2 = 0
for p in points:
if cross(ddp, deta(p, dp1)) < 0:
s2 = 1/2*abs(cross(ddp, deta(p, dp1)))
if s2 > maxS2:
maxS2 = s2
p2 = p
totalSpace = maxS1+maxS2
if totalSpace > maxSpace and p1 != (-1, -1) and p2 != (-1, -1):
maxSpace = copy.deepcopy(totalSpace)
tempList = [dp1, p1, dp2, p2]
img_bp = copy.deepcopy(img)
cv2.circle(img_bp, tempList[0],
15, (255, 48, 180), -1)
cv2.circle(img_bp, tempList[2],
15, (255, 48, 180), -1)
colour = 255
for p in tempList:
cv2.circle(img_bp, (int(p[0]), int(p[1])),
10, (colour, colour, colour), -1)
colour = colour - 85
3、图片处理效果
2、KNN
正在改LeNe5
数字识别(待改进)
[[0 0 5 0 6 0 0 5 0]
[1 1 7 0 0 0 0 8 0]
[0 0 0 9 8 0 0 5 6]
[0 0 0 8 0 6 8 0 0]
[4 0 3 0 0 0 1 0 9]
[0 0 1 3 0 1 0 0 0]
[1 1 0 0 3 1 0 0 0]
[0 1 0 0 0 0 3 8 1]
[0 1 0 0 1 0 4 0 0]]