### 在7段显示器上使用Python进行数字识别

我在Jupyter笔记本上使用Python编写代码,以识别7段显示器(FND)上的数字。

我使用了opencv并获取了图像的边缘。

import cv2import matplotlib.pyplot as plt def detect_edge(image):    ''' 检测边缘的函数 '''    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('/Users/USER/Desktop/test/test2.png', 0)detect_edge(image)

这是我从上述代码中得到的样本输入和输出的截图:

样本输入和输出

我不知道接下来该怎么做。我想识别这个例子中的数字51.12。

我应该先裁剪出数字所在的FND部分,然后再进行深度学习吗?

接下来我应该怎么做?


回答:

我觉得对于这样的问题使用CNN是小题大做。特别是考虑到这是7段显示器,我们应该能够在不使用这种复杂方法的情况下解决这个问题。

你已经标记了角点,所以我假设你可以可靠地裁剪并旋转(使其平整)显示器。

我们只想获取数字。在这种情况下,我首先转换为LAB颜色空间,并在b通道上进行阈值处理。输入图像描述

然后我使用opencv的findContours来标记周边:输入图像描述

之后我裁剪出每个单独的数字:

输入图像描述

然后我单独查找每个段,并根据哪些段是活跃的来确定数字(对于数字1,我使用了一个特殊情况,检查了宽度和高度的比例)。

输入图像描述

这是我使用的代码(两个文件)segments.py

import numpy as npclass Segments:    def __init__(self):        # 创建一个7段模型        self.flags = [];        self.segments = [];        h1 = [[0, 1.0],[0, 0.1]];       # 0        h2 = [[0, 1.0],[0.45, 0.55]];   # 1        h3 = [[0, 1.0],[0.9, 1.0]];     # 2        vl1 = [[0, 0.2],[0, 0.5]];      # 3 # 左上        vl2 = [[0, 0.2],[0.5, 1.0]];    # 4        vr1 = [[0.8, 1.0],[0, 0.5]];    # 5 # 右上        vr2 = [[0.8, 1.0], [0.5, 1.0]]; # 6        self.segments.append(h1);        self.segments.append(h2);        self.segments.append(h3);        self.segments.append(vl1);        self.segments.append(vl2);        self.segments.append(vr1);        self.segments.append(vr2);    # 处理图像并设置标志    def digest(self, number):        # 重置标志        self.flags = [];        # 检查是否为1        h, w = number.shape[:2];        if w < 0.5 * h:            self.flags.append(5);            self.flags.append(6);            return;        # 检查段        for a in range(len(self.segments)):            seg = self.segments[a];            # 获取边界            xl, xh = seg[0];            yl, yh = seg[1];            # 转换为像素坐标            xl = int(xl * w);            xh = int(xh * w);            yl = int(yl * h);            yh = int(yh * h);            sw = xh - xl;            sh = yh - yl;            # 检查            count = np.count_nonzero(number[yl:yh, xl:xh] == 255);            if count / (sh * sw) > 0.5: # 0.5是一个灵敏度度量                self.flags.append(a);    # 返回存储的数字(存储在self.flags中)    def getNum(self):        # 硬编码输出        if self.flags == [0,2,3,4,5,6]:            return 0;        if self.flags == [5,6]:            return 1;        if self.flags == [0,1,2,4,5]:            return 2;        if self.flags == [0,1,2,5,6]:            return 3;        if self.flags == [1,3,5,6]:            return 4;        if self.flags == [0,1,2,3,6]:            return 5;        if self.flags == [0,1,2,3,4,6]:            return 6;        if self.flags == [0,5,6]:            return 7;        if self.flags == [0,1,2,3,4,5,6]:            return 8;        if self.flags == [0,1,2,3,5,6]:            return 9;        # 错误        return -1;

main.py

import cv2import numpy as npfrom segments import Segments# 加载图像img = cv2.imread("seg7.jpg");# 裁剪img = img[300:800,100:800,:];# 转换为LAB颜色空间lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB);l,a,b = cv2.split(lab);# 显示cv2.imshow("orig", img);# 闭运算kernel = np.ones((5,5), np.uint8);# 阈值参数low = 165;high = 200;iters = 3;# 制作副本copy = b.copy();# 阈值处理thresh = cv2.inRange(copy, low, high);# 膨胀for a in range(iters):    thresh = cv2.dilate(thresh, kernel);# 腐蚀for a in range(iters):    thresh = cv2.erode(thresh, kernel);# 显示图像cv2.imshow("thresh", thresh);cv2.imwrite("threshold.jpg", thresh);# 开始处理_, contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);# 绘制for contour in contours:    cv2.drawContours(img, [contour], 0, (0,255,0), 3);# 获取每个数字的边界bounds = [];h, w = img.shape[:2];for contour in contours:    left = w;    right = 0;    top = h;    bottom = 0;    for point in contour:        point = point[0];        x, y = point;        if x < left:            left = x;        if x > right:            right = x;        if y < top:            top = y;        if y > bottom:            bottom = y;    tl = [left, top];    br = [right, bottom];    bounds.append([tl, br]);# 裁剪出每个数字cuts = [];number = 0;for bound in bounds:    tl, br = bound;    cut_img = thresh[tl[1]:br[1], tl[0]:br[0]];    cuts.append(cut_img);    number += 1;    cv2.imshow(str(number), cut_img);# 字体 font = cv2.FONT_HERSHEY_SIMPLEX;# 创建一个段模型model = Segments();index = 0;for cut in cuts:    # 保存图像    cv2.imwrite(str(index) + "_" + str(number) + ".jpg", cut);    # 处理    model.digest(cut);    number = model.getNum();    print(number);    cv2.imshow(str(index), cut);    # 再次绘制并保存    h, w = cut.shape[:2];    drawn = np.zeros((h, w, 3), np.uint8);    drawn[:, :, 0] = cut;    drawn = cv2.putText(drawn, str(number), (10,30), font, 1, (0,0,255), 2, cv2.LINE_AA);    cv2.imwrite("drawn" + str(index) + "_" + str(number) + ".jpg", drawn);        index += 1;    # cv2.waitKey(0);# 显示cv2.imshow("contours", img);cv2.imwrite("contours.jpg", img);cv2.waitKey(0);

我不能保证这总是有效的,但在进行一些调整后应该可以使用。记得如果图像不是平的,要对其进行旋转。段模型假设数字大多是直立的。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注