Recognizing numbers using OpenCV and python

AI Hao 2021-11-25 11:27:33
recognizing numbers using opencv python

Use OpenCV and Python Identification Numbers

This article demonstrates how to use OpenCV and Python Recognize the numbers in the image .

In the first part of this tutorial , We will discuss what is a seven segment display , And how we apply computer vision and image processing operations to identify these types of numbers ( No need for machine learning !)

Seven segment display

You may already be familiar with the seven segment monitor , Even if you don't know a particular term . A good example of this display is your classic digital alarm clock :


Each number on the alarm clock is represented by a seven segment component , As shown below :


The seven segment display can present a total of 128 All possible states :


We are only interested in 10 I'm interested in —— Numbers 0 To 9:


Our goal is to write OpenCV and Python Code to identify each of the ten digital states in the image .

Design OpenCV Digital recognizer

We will use the thermostat image as input :


The steps of identification :

step 1: Position the... On the thermostat LCD. This can be done using edge detection , Because the plastic shell and LCD There is enough contrast between .

step 2: extract LCD. Given an input edge graph , I can find the outline and look for the outline of the rectangle —— The largest rectangular area should correspond to LCD. Perspective transformation will give me a good LCD extract .

step 3: Extract the digital area . Once I have LCD In itself , I can focus on extracting numbers . Due to the digital area and LCD There seems to be a contrast between the backgrounds , I believe that threshold and morphological operations can achieve this .

step 4: Identification Numbers . Use OpenCV Identifying actual numbers will involve ROI Divided into seven parts . From there, I can apply pixel counts to the threshold image to determine whether a given segment is “ open ” still “ Turn off ”.

So let's see how we use OpenCV and Python Complete this four step process for number recognition , Read on .

Use computer vision and OpenCV Identification Numbers

Let's continue with this example . Create a new file , I'm going to call it , And insert the following code :

# 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

(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

Import what we need Python package . introduce mutils, This is my series of convenience functions , Can be used more easily OpenCV + Python. If you have not already installed imutils, It's time to use pip Install the package on your system : Use OpenCV and Python Identification Numbers

pip install imutils

Define a name DIGITS_LOOKUP Of Python Dictionaries . Their key to the table is a seven segment array . Array 1 Indicates that the given segment is open , Zero indicates that the segment is closed . The value is the actual number itself :0-9.

Once we identify the segment in the thermostat display , We can pass the array to our DIGITS_LOOKUP In the table and obtain numerical values . As a reference , The dictionary uses the same as the figure above 2 The same segment order in . Let's continue with our example :

# load the example image
image = cv2.imread("example.jpg")
# pre-process the image by resizing it, converting it to
# graycale, blurring it, and computing an edge map
image = imutils.resize(image, height=500)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 50, 200, 255)

Load our image .

Then we preprocess the image in the following ways :-

  • Resize .
  • Convert the image to grayscale .
  • Use 5×5 The kernel applies Gaussian blur to reduce high-frequency noise .
  • adopt Canny The edge detector calculates the edge map .

After applying these preprocessing steps , Our edge graph is shown below :


Be careful LCD How the outline of the is clearly visible —— This completes the steps #1. We can now move on to the second 2 Step , extract LCD In itself :

# find contours in the edge map, then sort them by their
# size in descending order
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
displayCnt = None
# loop over the contours
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
# if the contour has four vertices, then we have found
# the thermostat display
if len(approx) == 4:
displayCnt = approx

In order to find LCD Area , We need to extract the contour of the region in the edge graph ( That is, contour ).

Then we sort the contours by area , Make sure to place the larger contour line at the front of the list .

Give us a sorted outline list , Cycle them one by one and apply contour approximation .

If our approximate contour has four vertices , So let's assume we've found the thermostat display . This is a reasonable assumption , Because the largest rectangular area in our input image should be LCD In itself .

After getting four vertices , We can extract... Through four point perspective transformation LCD:

# extract the thermostat display, apply a perspective transform
# to it
warped = four_point_transform(gray, displayCnt.reshape(4, 2))
output = four_point_transform(image, displayCnt.reshape(4, 2))

Applying this perspective transformation provides us with a top-down LCD Aerial view :


get LCD This view of meets the requirements of 2 Step —— We are now ready to start from LCD Extract numbers from :

# threshold the warped image, then apply a series of morphological
# operations to cleanup the thresholded image
thresh = cv2.threshold(warped, 0, 255,
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1, 5))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

In order to get the number itself , We need to threshold the distorted image , On a brighter background ( namely LCD The background of the display ) Show dark areas in ( The digital ):


Then we apply a series of morphological operations to clean up the threshold image :


Now we have a good segmentation image , We need to apply contour filtering again , Only this time we are looking for the actual number :

# find contours in the thresholded image, then initialize the
# digit contours lists
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cnts = imutils.grab_contours(cnts)
digitCnts = []
# loop over the digit area candidates
for c in cnts:
# compute the bounding box of the contour
(x, y, w, h) = cv2.boundingRect(c)
# if the contour is sufficiently large, it must be a digit
if w >= 15 and (h >= 30 and h <= 40):

So , We find the contour in the threshold image . initialization digitsCnts list —— This list will store the outline of the number itself .

Cycle through each contour .

For each profile , We calculate the bounding box , Make sure the width and height are acceptable , If it is , Update digitsCnts list .

If we loop through digitsCnts Outline the interior and draw a bounding box on the image , The results will be as follows :


Sure enough , We found the number on the LCD ! The last step is to actually identify each number :

# sort the contours from left-to-right, then initialize the
# actual digits themselves
digitCnts = contours.sort_contours(digitCnts,
digits = []

ad locum , We're just based on (x, y) The coordinates sort the digital contours from left to right .

This sorting step is necessary , Because there is no guarantee that the outline has been sorted from left to right ( In the same direction we read numbers ).

Next is the actual number recognition process :

# loop over each of the digits
for c in digitCnts:
# extract the digit ROI
(x, y, w, h) = cv2.boundingRect(c)
roi = thresh[y:y + h, x:x + w]
# compute the width and height of each of the 7 segments
# we are going to examine
(roiH, roiW) = roi.shape
(dW, dH) = (int(roiW * 0.25), int(roiH * 0.15))
dHC = int(roiH * 0.05)
# define the set of 7 segments
segments = [
((0, 0), (w, dH)), # top
((0, 0), (dW, h // 2)), # top-left
((w - dW, 0), (w, h // 2)), # top-right
((0, (h // 2) - dHC) , (w, (h // 2) + dHC)), # center
((0, h // 2), (dW, h)), # bottom-left
((w - dW, h // 2), (w, h)), # bottom-right
((0, h - dH), (w, h)) # bottom
on = [0] * len(segments)

Traverse each digital contour .

For each of these areas , We calculate the bounding box and extract the number ROI.

I include each number below ROI Of GIF Animation :

 Insert picture description here

Given number ROI, We now need to locate and extract the seven parts of the digital display .

according to ROI Dimension calculate the approximate width and height of each segment . Then we define a (x, y) Coordinates the list , These coordinates correspond to seven line segments . This list follows the figure above 2 Same segment order . This is an example GIF Animation , It draws a green box on the current clip being investigated :

Figure 12: An example of drawing the segment ROI for each of the seven segments of the digit.

Last , Initialize our on list —— The values in this list 1 Indicates that the given segment is “ open ” Of , A value of zero indicates that the segment is “ closed ”. Given seven display segments (x, y) coordinate , It is quite easy to identify whether a segment is open or closed :

# loop over the segments
for (i, ((xA, yA), (xB, yB))) in enumerate(segments):
# extract the segment ROI, count the total number of
# thresholded pixels in the segment, and then compute
# the area of the segment
segROI = roi[yA:yB, xA:xB]
total = cv2.countNonZero(segROI)
area = (xB - xA) * (yB - yA)
# if the total number of non-zero pixels is greater than
# 50% of the area, mark the segment as "on"
if total / float(area) > 0.5:
on[i]= 1
# lookup the digit and draw it on the image
digit = DIGITS_LOOKUP[tuple(on)]
cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 1)
cv2.putText(output, str(digit), (x - 10, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 255, 0), 2)

We start looping through each line segment (x, y) coordinate .

We extract fragments ROI, Then calculate the non-zero pixel number ( That is, in the fragment “ Turn on ” The number of pixels ).

If the ratio of non-zero pixels to the total area of the segment is greater than 50%, Then we can assume that the paragraph is “on” And update our... Accordingly on list . After seven stages of the cycle , We can pass the list to DIGITS_LOOKUP To get the number itself .

Then we draw a bounding box around the number and display the number on the output image . Last , Our last code block prints the number onto our screen and displays the output image :

# display the digits
print(u"{}{}.{} \u00b0C".format(*digits))
cv2.imshow("Input", image)
cv2.imshow("Output", output)

Please note how we use Python and OpenCV Correctly identify LCD The numbers on the screen :



In today's blog post , I demonstrated how to use OpenCV and Python To identify the numbers in the image .

This method is specifically used for seven segment displays ( That is, the digital display you usually see on the digital alarm clock ).

By extracting each of the seven segments and applying basic threshold and morphological operations , We can determine which paragraphs are “ open ” Of , Which are “ Turn off ” Of .

From there, , We can do it in Python Find open... In dictionary data structure / Close the section to quickly determine the actual number —— No machine learning required !

As I mentioned at the beginning of this blog post , The application of computer vision to identify the numbers in the thermostat image often makes the problem itself too complex —— Using a data recording thermometer will be more reliable , And the workload is much less .

I hope you like today's blog !

本文为[AI Hao]所创,转载请带上原文链接,感谢

  1. Utilisez Python pour proposer l'année de la colonne de date dans les deux CSV, faire une nouvelle colonne, puis combiner les deux tableaux CSV en un seul tableau avec la colonne de date et le numéro d'identification.
  2. 关于#python#的问题,请各位专家解答!
  3. ***
  4. ***
  5. 關於#python#的問題,請各比特專家解答!
  6. S'il vous plaît répondre aux questions de Python!
  7. About the import of Python class
  8. Magic Python property decorator: 1 line of code makes Python methods become properties in seconds
  9. Python 音频调整音量(附代码) | Python工具
  10. Python programming ideas [series of articles]
  11. Python crawler programming idea (67): modify nodes using pyquery
  12. Python crawler programming idea (66): using pyquery to obtain node information
  13. Python crawler programming idea (65): find nodes using pyquery
  14. Python crawler programming idea (64): using CSS selectors in pyquery
  15. Python crawler programming idea (63): basic knowledge of pyquery
  16. Python crawler programming idea (62): project practice: capturing cool dog online red song list
  17. Python crawler programming idea (61): project practice: capturing rental information
  18. Python crawler programming idea (60): get CSS selector code through browser
  19. Python爬虫编程思想(85):在Python中使用非关系型数据库
  20. Volume de réglage audio Python (avec Code) | outils Python
  21. Python crawler programming idea (59): get attribute value and text with beautiful soup CSS selector
  22. Python crawler programming idea (58): nested selection nodes with beautiful soup CSS selectors
  23. Python crawler programming idea (57): basic usage of CSS selector in beautiful soup
  24. Python crawler programming idea (56): find method of beautiful soup method selector
  25. Python crawler programming idea (55): find of beautiful soup method selector_ All method
  26. Python crawler programming idea (54): use beautiful soup to select sibling nodes
  27. Python crawler programming idea (53): use beautiful soup to select the parent node
  28. Django3.0 solves the problem of error reporting in reverse parsing
  29. Precautions for Python crawler
  30. Python 3 crawler series (1) -- climbing blind date websites
  31. Python到底是什么?为什么要学Python?
  32. #yyds干货盘点#Pandas数据清洗实用指南
  33. Python打包exe文件无法运行
  34. Two common ways to save files in Python
  35. #yyds幹貨盤點#Pandas數據清洗實用指南
  36. Yyds Dry Inventory pandas Data Cleaning Practical Guide
  37. PYTHON用LSTM长短期记忆神经网络的参数优化方法预测时间序列洗发水销售数据
  38. Python集成学习:自己编写构建AdaBoost分类模型可视化决策边界及sklearn包调用比较
  39. Python 3 makes a search software
  40. Python 3 simulated microblog login
  41. Using Python 3 to make practical software for drawing modification
  42. About HTML (acceptable to Python)
  43. Python集成學習:自己編寫構建AdaBoost分類模型可視化决策邊界及sklearn包調用比較
  44. PYTHON用LSTM長短期記憶神經網絡的參數優化方法預測時間序列洗發水銷售數據
  45. Python Integrated Learning: Writing and Constructing adaboost Classification Model Visualized decision Boundary and sklearn package Calling Comparison
  46. Python prédit les données de vente de shampooing de séries chronologiques en utilisant la méthode d'optimisation des paramètres du réseau neuronal de mémoire à court et à long terme lstm
  47. [zero basics of Python to introduction] a prerequisite for Python preparatory knowledge -- basic coding specification of Python
  48. OpenCV对比度亮度变换竟能用来去水印(附Python/C++源码)
  49. [zero basics of Python to getting started] a prerequisite for Python preparatory knowledge -- installing the visualization tool pycharm
  50. The test modifies in micro python
  51. Microphoton experimental circuit board based on mm32f3273 - does not work normally
  52. Run micropathon on mm32f3273 to test performance
  53. Design mm32f3277 micro Python experimental board with SD card
  54. Mm32f3277 corresponding interface files during microphoton migration
  55. Mm32f3277 microphoton experimental board design and software testing
  56. Making and testing mm32f3277 microphoton minimum circuit board
  57. Download mm32-link program automatically with Python simulated mouse
  58. A curriculum of "artificial intelligence Python machine learning and deep learning"
  59. Test the basic functions of mm32 microphoton test circuit board
  60. Test the basic functions of the mm32f3277 micro Python development board flying one by one