问题
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()
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.
回答1:
Here's an approach using the thresholded input image you have provided
- Convert image to grayscale and Otsu's threshold
- Perform morph close with a horizontal kernel to merge the numbers into a single contour
- Find contours and filter using a minimum threshold area to filter out the large outer contour
- Sort by largest contour area which should be the desired text contour
- Iterate through contours and extract ROI using Numpy slicing
Starting from your input image
We morph close using a horizontal kernel to merge the numbers together into a single contour
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
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()
来源:https://stackoverflow.com/questions/58663227/extracting-digits-from-image-with-python-and-opencv