使用python和OpenCV从图像中提取数字 [英] Extracting digits from image with python and OpenCV

查看:236
本文介绍了使用python和OpenCV从图像中提取数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一些编码解决方案/帮助,以从LCD显示屏中提取数字,然后从图像中输出值.

I am looking for some coding solution/help to extract the digits from the LCD display and then output the value from the image.

下面是代码和示例图像以及到目前为止的效果,但是我需要进一步的帮助才能从图像中实际提取数字"并输出值.

Below is the code and example images and how I got so far, but I need some further help to actually extract the "digits" from the image and output the value.

我已经根据较早的示例制作了数字查找表

I have made digits lookup table from an earlier example,

# import the necessary packages
from imutils.perspective import four_point_transform
from imutils import contours
import imutils
import cv2

# define the dictionary of digit segments so we can identify
# each digit on the thermostat
DIGITS_LOOKUP = {
(1, 1, 1, 0, 1, 1, 1): 0,
(0, 0, 1, 0, 0, 1, 0): 1,
(1, 0, 1, 1, 1, 1, 0): 2,
(1, 0, 1, 1, 0, 1, 1): 3,
(0, 1, 1, 1, 0, 1, 0): 4,
(1, 1, 0, 1, 0, 1, 1): 5,
(1, 1, 0, 1, 1, 1, 1): 6,
(1, 0, 1, 0, 0, 1, 0): 7,
(1, 1, 1, 1, 1, 1, 1): 8,
(1, 1, 1, 1, 0, 1, 1): 9}

# load the example image
image = cv2.imread("Multimeter_1.jpg")

# pre-process the image by converting it to
# graycale, blurring it, and computing an edge map
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (7,7), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,87,9)


# find contours in the edge map,
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

rect = None
# loop over the contours
for c in cnts:
# approximate the contour
x,y,w,h = cv2.boundingRect(c)
#cv2.rectangle(image, (x, y), (x+w, y+h), (36, 255, 12), 1)
cv2.drawContours(image, [c], -1, (36,255,12),3)
rect = c

peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)

if len(approx) == 4:
    rect = approx
    break


# extract the display, apply a perspective transform

warped = four_point_transform(thresh, rect.reshape(4, 2))
output = four_point_transform(image, rect.reshape(4, 2))

# Warp the image and perform morphology to clean it

thresh = cv2.threshold(warped, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)


# pre-process the image by converting it to
# graycale, blurring it, and computing an edge map
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (7,7), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,87,9)


# find contours in the edge map,
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

rect = None
# loop over the contours
for c in cnts:
# approximate the contour
x,y,w,h = cv2.boundingRect(c)
#cv2.rectangle(image, (x, y), (x+w, y+h), (36, 255, 12), 1)
cv2.drawContours(image, [c], -1, (36,255,12),3)
rect = c

peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.05 * peri, True)

if len(approx) == 4:
    rect = approx
    break


# extract the display, apply a perspective transform

warped = four_point_transform(thresh, rect.reshape(4, 2))
output = four_point_transform(image, rect.reshape(4, 2))
# Warp the image and perform morphology to clean it

thresh = cv2.threshold(warped, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1, 5))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

cnts = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
digitCnts = []

# loop over the digit area candidates
for c in cnts:
(x,y,w,h) = cv2.boundingRect(c)

# if the contour is sufficiently large, it must be a digit
if w >= 25 and (h >= 50 and h <= 60):
    digitCnts.append(c)





cv2.imshow("Multimeter", image)
cv2.imshow("Threshed", thresh)
cv2.imwrite("Threshed.jpg",thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

在python方面,特别是在Open CV中非常熟练的人可以帮助我解决这个问题吗?这是有关图像处理部分的学校作业,我决定使用Python和OpenCV,因此它不是编程作业,而代码将仅用于做和解释实际的图像处理.我只需要帮助就可以从经过剔除的图像中实际提取出数字.我还提供了LCD显示屏上的原始图像,以防万一有更好的方法来实现我想要的.

Can someone very profiecient in python, especially in Open CV help me out with this. This is a school assignment about the image process part and I have decided to use Python and OpenCV, so it is not a programming assignment and the code will be used just to do and explain the actual image processing nothing less or more. I just need help to actually extract the digits out of the treshed image. I also provided the original image from the LCD display in case there is a better method to achieve what I am looking for.

推荐答案

这是一种使用您提供的阈值输入图像的方法

Here's an approach using the thresholded input image you have provided

  • 将图像转换为灰度并达到Otsu的阈值
  • 使用水平内核执行变形闭合以将数字合并为单个轮廓
  • 查找轮廓并使用最小阈值区域进行滤波以滤除较大的外部轮廓
  • 按最大轮廓区域排序,该区域应为所需的文本轮廓
  • 遍历轮廓并使用Numpy切片提取ROI

从输入图片开始

我们使用水平核将数字进行合并以将数字合并到一个轮廓中

We morph close using a horizontal kernel to merge the numbers together into a single contour

从这里我们找到轮廓并进行过滤,以仅将轮廓保持在阈值区域以下.具体来说,我们使用 0.75 * w * h 过滤掉外部轮廓.完成此操作后,所需的文本轮廓应为最大轮廓

From here we find contours and filter to only keep contours that are below a threshold area. Specifically, we use 0.75 * w * h to filter out the outer contours. Once we do this, the desired text contour should be the largest contour

最后,我们使用 cv2.boundingRect()和Numpy切片

Finally we extract the ROI using cv2.boundingRect() and Numpy slicing

import cv2

image = cv2.imread('1.jpg')
original = image.copy()
h, w, _ = image.shape

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,1))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
minimum_area = .75 * h * w
cnts = [c for c in cnts if cv2.contourArea(c) < minimum_area]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    ROI = 255 - original[y:y+h, x:x+w]
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
    break

cv2.imshow('close', close)
cv2.imshow('image', image)
cv2.imshow('ROI', ROI)
cv2.waitKey()

这篇关于使用python和OpenCV从图像中提取数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆