今天想要构建自己的MNIST数据集,但是一个一个手画然后拍照再把数字一个一个抠出来实在是太耗时了,所以想用程序解决这个问题:
下面附上程序:(备注:里面的代码是在之前某个博主的代码基础上改装过来的,具体是哪个我已经不记得了)
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 反相灰度图,将黑白阈值颠倒
def accessPiexl(img):
height = img.shape[0]
width = img.shape[1]
for i in range(height):
for j in range(width):
img[i][j] = 255 - img[i][j]
return img
# 反相二值化图像
def accessBinary(img, threshold=200):
img = accessPiexl(img)
# 边缘膨胀,不加也可以
kernel = np.ones((3, 3), np.uint8)
img = cv2.dilate(img, kernel, iterations=1)
_, img = cv2.threshold(img, threshold, 0, cv2.THRESH_TOZERO)
return img
# 寻找边缘,返回边框的左上角和右下角(利用cv2.findContours)
def findBorderContours(path, maxArea=50):
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)#(cv2.IMREAD_GRAYSCALE)按灰度模式读取图像
img = accessBinary(img)
contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)#(cv2.RETR_EXTERNAL)检测边缘,(cv2.CHAIN_APPROX_NONE)绘制
borders = []
border_sortt = []
# print("打印",hierarchy)
for contour in contours:
# 将边缘拟合成一个边框
x, y, w, h = cv2.boundingRect(contour)
if w*h > maxArea:
border = [(x, y), (x+w, y+h)]
borders.append(border)
return borders
# 显示结果及边框
def Save_Results(path, borders):
img = cv2.imread(path)
# 绘制
print(img.shape)
for i, border in enumerate(borders):
print("border = ",border)
pic = img[border[0][1] - 30 :border[1][1] + 30 , border[0][0] - 30 : border[1][0] + 30]
# cv2.imshow("img",pic)
# cv2.waitKey(0)
cv2.imwrite("D:/0000{num}.jpg".format(num=i),pic)
if __name__ == '__main__':
# 综合测试
path = './1.jpg'
borders = findBorderContours(path) #要抠图的原图片
Aave_Results(path, borders)
显示效果:
原图:
处理后的: