How to check if a point is in an ellipse in python - python-3.x

How do I find a point within an angled ellipse in python? I wrote out the equation in a function and I am drawing a black picture with the ellipse in white and the point in blue. I am then calculating if the point is within the ellipse which it is showing up in the picture but the function is returning as false. What am I missing?
Thanks!
# Create a black image for ellipse ROI
img = np.zeros((240, 320, 3), np.uint8)
# ellipse
ellipse_center_x = 160
ellipse_center_y = 120
ellipse_axis_x = 100
ellipse_axis_y = 20
ellipse_angle = -40
start_angle = 0
end_angle = 360
# detection point example
xCenter = 135
yCenter = 135
def pointInEllipse(img, xp, yp, x, y, axis_x, axis_y, angle):
# # WITH StackOverflow Answer Edits
angle_rad = math.radians(angle)
cosa = math.cos(angle_rad)
sina = math.sin(angle_rad)
# # Equation of point within angled ellipse
a = (((cosa * (xp - x) + sina * (yp - y)) ** 2) / (axis_x**2))
b = (((sina * (xp - x) - cosa * (yp - y)) ** 2) / (axis_y**2))
result = a+b
img = cv2.ellipse(img, (x, y), (axis_x, axis_y), angle, 0, 360, (255, 255, 255), 1)
if result <= 1:
img = cv2.circle(img, (xp, yp), 10, (255, 0, 0), -1)
print(result)
cv2.imwrite('/tmp/ellipse2.png', img)
return True
else:
img = cv2.circle(img, (xp, yp), 10, (255, 0, 0), -1)
print(result)
cv2.imwrite('/tmp/ellipse2.png', img)
return False
print(pointInEllipse(img, xCenter, yCenter, ellipse_center_x, ellipse_center_y, ellipse_axis_x, ellipse_axis_y,ellipse_angle))

The cosa and sina values are wrong: math.sin and math.cos expect their arguments in radians (0 to 2π for a full circle), but you are passing an angle in degrees.
To convert an angle from degrees to radians, use the math.radians function:
angle_rad = math.radians(angle)
cosa = math.cos(angle_rad)
sina = math.sin(angle_rad)

Related

How to detect free space between two detected windows

I used YOLOv3 to detect windows on the building. Each window shows with a bounding box around, also I extracted coordinates of each window [top_left, bottom_left, top_right, bottom_right]. now I want to find free space[wall] between all the windows. I put the coordinates of each window in a Dict.
when I set the values manually it works for each window for instance:
p1 = points_list[0][2] # top_left window1
p2 = points_list[1][1] # bottom_left window2
cv2.rectangle(img, p1, p2, (255, 0, 255), -1)
, but how can I make it automatically to find walls.
Here is my first output image, the detected wall shows by pink color.
here also I have added a sample of my code.
def bb_to_rect(x, y, w, h):
top_left = (x, y)
top_right = (x + w, y)
bottom_left = (x, y + h)
bottom_right = (x + w, y + h)
return top_left, bottom_left, top_right, bottom_right
def draw_bounding_box(img, font, boxes, confidences, colors):
indices = cv2.dnn.NMSBoxes(boxes, confidences, CONF_THRESHOLD, NMS_THRESHOLD)
points_list={}
count = 0
for i in range(len(boxes)):
if i in indices:
(x, y, w, h) = boxes[i]
label = "{}:{:.2f}%".format(classes[class_ids[i]], confidences[i] * 100)
color = colors[class_ids[i]]
cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
cv2.putText(img, str(i), (x, y), cv2.FONT_HERSHEY_TRIPLEX,
.5, (255, 255, 0), 1, cv2.LINE_AA)
top_left, bottom_left, top_right, bottom_right = bb_to_rect(x, y, w, h)
points_list[count] = [top_left, bottom_left, top_right, bottom_right]
count += 1
cv2.circle(img, (x + w, y), 3, (50, 100, 0), -1) # top Right
cv2.circle(img, (x + w, y + h), 3, (0, 0, 255), -1) # bottom Right
cv2.circle(img, (x, y), 3, (0, 255, 100), -1) # top left
cv2.circle(img, (x, y + h), 3, (255, 0, 255), -1) # bottom left
return img, points_list
if __name__ == "__main__":
net, output_layers, colors, classes = load_yolo_model()
img, height, width = load_img(IMAGES_PATH)
outs = create_blob(img, net, output_layers)
boxes, class_ids, confidences, centroids = detect_obj(outs, height, width, img)
img, points_list = draw_bounding_box(img, FONT, boxes, confidences, colors)
p1 = points_list[0][2] # window0 to window1
p2 = points_list[1][1]
p2_1 = points_list[1][2] # window1 to window2
p2_2 = points_list[2][1]
p3_1 = points_list[3][2] # window3 to window5
p5_2 = points_list[5][1]
cv2.rectangle(img, p1, p2, (255, 0, 255), -1)
cv2.rectangle(img, p2_1, p2_2, (255, 0, 255), -1)
cv2.rectangle(img, p3_1, p5_2, (255, 0, 255), -1)
cv2.imshow('out', img)
cv2.waitKey(0)
Also if you see the photo you will see the windows detected randomly and the Id number for each window does not order. How can I solve this problem? thanks in advance for helping:)
Have you tried Image Segmentation to find the objects on wall? then with a simple trick like finding the countors you can measure the distance between the objects like windows as you said.
2nd trick:
I've got another easy way which may help you:
first of all, find the edges using canny edg detection, the with dilate function fill the middle space of vertical edges between windows then by Hough Line Detection you can find the vertical lines of windows, and get the distance between the y axis of vertical lines of the wall.

How to recognize and count circles in a rectangle?

I would like to count how many circles are in static rectangles for more than 3 seconds. The circles represent the center of objects recognized by the camera and static rectangles are areas of interest where I would like to count the total amount of circles that are inside the area of interest for more than 3 seconds. Currently I am able to recognize objects in real-time, find the center of each object and draw static rectangles, but I don't know how to do the rest. Below is my current while loop. Any help would be greatly appreciated.
while True:
frame = vs.read()
frame = imutils.resize(frame, width=720)
box_one = cv2.rectangle(frame, (30,30), (330,330), color, 2)
box_two = cv2.rectangle(frame, (350,30), (630,330), color, 2)
(h, w) = frame.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)),
0.007843, (300, 300), 127.5)
net.setInput(blob)
detections = net.forward()
for i in np.arange(0, detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence > args["confidence"]:
idx = int(detections[0, 0, i, 1])
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
label = "{}: {:.2f}%".format(CLASSES[idx],
confidence * 100)
cv2.rectangle(frame, (startX, startY), (endX, endY),
COLORS[idx], 2)
center = ((startX+endX)/2, (startY+endY)/2)
first_value = int(center[0])
second_value = int(center[1])
coordinates = (first_value, second_value)
cv2.circle(frame, coordinates, 5, (255,255,255), -1)
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
The output looks like this

How to plot 3D voxels with given coordinates on a sphere using matplotlib

I'm currently trying to make a 3D voxels plot with know coordinates on a sphere. The x, y and z coordinates are lists filtered from a CSV. Additionally I have another list with same length as x, y and z containing the color of the voxel. With these list I want to create a 3D voxel sphere.
This I already accomplished using a 3D scatter plot (matplotlib) but the result is not very clear:
x = []
y = []
z = []
c = []
red = (1, 0, 0, 1)
green = (0, 1, 0, 1)
blue = (0, 0, 1, 1)
black = (0, 0, 0, 1)
for i in range(len(result)):
x.append(20 * math.sin(math.radians(90 - result[i][1])) * math.cos(math.radians(result[i][0])))
y.append(20 * math.sin(math.radians(90 - result[i][1])) * math.sin(math.radians(result[i][0])))
z.append(20 * math.cos(math.radians(90 - result[i][1])))
if result[i][2] == 1000:
c.append(black)
elif result[i][2] > 500:
c.append(red)
elif 200 < result[i][2] <= 500:
c.append(blue)
else:
c.append(green)
fig = pyplot.figure()
ax = Axes3D(fig)
ax.grid(True)
ax.scatter(x, y, z, c=c, s=500)
pyplot.show()
3D-Scatter

White Balance a photo from a known point

White Balancing is a rather well-covered topic, but most of the answers I have seen cover automatic white balancing techniques for an entire image that does not have a known point for what is white, gray, and black. I cannot seem to find many that cover white balancing from a known point. I have the script (below) that takes an image of a color card (Spyder Checkr 48) and returns the white, 20% Gray, and Black color card blocks:
Color L A B sR sG sB aR aG aB
Card White 96.04 2.16 2.6 249 242 238 247 242 237
20% Gray 80.44 1.17 2.05 202 198 195 199 196 193
Card Black 16.91 1.43 -0.81 43 41 43 46 46 47
Question: Since I know the ground truth LAB, sRGB and AdobeRGB values for specific parts of the image, what would be the best way to white balance the image?
Here is a link to the images I am working with. This is the code for extracting the color card blocks (I currently am running this on Windows, Python 3.7):
from __future__ import print_function
import cv2
import imutils
import numpy as np
from matplotlib import pyplot as plt
import os
import sys
image = cv2.imread("PATH_TO_IMAGE")
template = cv2.imread("PATH_TO_TEMPLATE")
rtemplate = cv2.imread("PATH_TO_RIGHT_TEMPLATE")
def sift(image):
sift = cv2.xfeatures2d.SIFT_create()
kp, des = sift.detectAndCompute(image, None)
return kp, des
def sift_match(im1, im2, vis=False, save=False):
MIN_MATCH_COUNT = 10
FLANN_INDEX_KDTREE = 0
kp1, des1 = sift(im1)
kp2, des2 = sift(im2)
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=7)
search_params = dict(checks=100)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# Need to draw only good matches, so create a mask
matchesMask = [[0, 0] for i in range(len(matches))]
if vis is True:
draw_params = dict(matchColor=(0, 255, 0),
singlePointColor=(255, 0, 0),
matchesMask=matchesMask,
flags=0)
im3 = cv2.drawMatchesKnn(im1, kp1, im2, kp2, matches, None, **draw_params)
if save:
cv2.imwrite("tempSIFT_Match.png", im3)
plt.imshow(im3), plt.show()
good = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good.append(m)
return kp1, des1, kp2, des2, good
def smartextractor(im1, im2, vis=False):
# Detect features and compute descriptors.
kp1, d1, kp2, d2, matches = sift_match(im1, im2, vis)
kp1 = np.asarray(kp1)
kp2 = np.asarray(kp2)
# Extract location of good matches
points1 = np.zeros((len(matches), 2), dtype=np.float32)
points2 = np.zeros((len(matches), 2), dtype=np.float32)
for i, match in enumerate(matches):
points1[i, :] = kp1[match.queryIdx].pt
points2[i, :] = kp2[match.trainIdx].pt
# Find homography
h, mask = cv2.findHomography(points1, points2, cv2.RANSAC)
if h is None:
print("could not find homography")
return None, None
# Use homography
height, width, channels = im2.shape
im1Reg = cv2.warpPerspective(im1, h, (width, height))
return im1Reg, h
def show_images(images, cols=1, titles=None):
"""
Display a list of images in a single figure with matplotlib.
"""
assert ((titles is None) or (len(images) == len(titles)))
n_images = len(images)
if titles is None: titles = ['Image (%d)' % i for i in range(1, n_images + 1)]
fig = plt.figure()
for n, (image, title) in enumerate(zip(images, titles)):
a = fig.add_subplot(cols, np.ceil(n_images / float(cols)), n + 1)
if image.ndim == 2:
plt.gray()
plt.imshow(image)
a.set_title(title)
fig.set_size_inches(np.array(fig.get_size_inches()) * n_images)
plt.show()
def Sobel(img, bilateralFilter=True):
# timestart = time.clock()
try:
img = cv2.imread(img, 0)
except TypeError:
None
try:
rheight, rwidth, rdepth = img.shape
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
except ValueError:
raise TypeError
# cv2.imwrite('temp.png',img)
_, s, v = cv2.split(img1)
b, g, r = cv2.split(img)
if bilateralFilter is True:
s = cv2.bilateralFilter(s, 11, 17, 17)
v = cv2.bilateralFilter(v, 11, 17, 17)
b = cv2.bilateralFilter(b, 11, 17, 17)
g = cv2.bilateralFilter(g, 11, 17, 17)
r = cv2.bilateralFilter(r, 11, 17, 17)
# calculate sobel in x,y,diagonal directions with the following kernels
sobelx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=np.float32)
sobely = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], dtype=np.float32)
sobeldl = np.array([[0, 1, 2], [-1, 0, 1], [-2, -1, 0]], dtype=np.float32)
sobeldr = np.array([[2, 1, 0], [1, 0, -1], [0, -1, -2]], dtype=np.float32)
# calculate the sobel on value of hsv
gx = cv2.filter2D(v, -1, sobelx)
gy = cv2.filter2D(v, -1, sobely)
gdl = cv2.filter2D(v, -1, sobeldl)
gdr = cv2.filter2D(v, -1, sobeldr)
# combine sobel on value of hsv
xylrv = 0.25 * gx + 0.25 * gy + 0.25 * gdl + 0.25 * gdr
# calculate the sobel on saturation of hsv
sx = cv2.filter2D(s, -1, sobelx)
sy = cv2.filter2D(s, -1, sobely)
sdl = cv2.filter2D(s, -1, sobeldl)
sdr = cv2.filter2D(s, -1, sobeldr)
# combine sobel on value of hsv
xylrs = 0.25 * sx + 0.25 * sy + 0.25 * sdl + 0.25 * sdr
# combine value sobel and saturation sobel
xylrc = 0.5 * xylrv + 0.5 * xylrs
xylrc[xylrc < 6] = 0
# calculate the sobel on value on green
grx = cv2.filter2D(g, -1, sobelx)
gry = cv2.filter2D(g, -1, sobely)
grdl = cv2.filter2D(g, -1, sobeldl)
grdr = cv2.filter2D(g, -1, sobeldr)
# combine sobel on value on green
xylrgr = 0.25 * grx + 0.25 * gry + 0.25 * grdl + 0.25 * grdr
# calculate the sobel on blue
bx = cv2.filter2D(b, -1, sobelx)
by = cv2.filter2D(b, -1, sobely)
bdl = cv2.filter2D(b, -1, sobeldl)
bdr = cv2.filter2D(b, -1, sobeldr)
# combine sobel on value on blue
xylrb = 0.25 * bx + 0.25 * by + 0.25 * bdl + 0.25 * bdr
# calculate the sobel on red
rx = cv2.filter2D(r, -1, sobelx)
ry = cv2.filter2D(r, -1, sobely)
rdl = cv2.filter2D(r, -1, sobeldl)
rdr = cv2.filter2D(r, -1, sobeldr)
# combine sobel on value on red
xylrr = 0.25 * rx + 0.25 * ry + 0.25 * rdl + 0.25 * rdr
# combine value sobel and saturation sobel
xylrrgb = 0.33 * xylrgr + 0.33 * xylrb + 0.33 * xylrr
xylrrgb[xylrrgb < 6] = 0
# combine HSV and RGB sobel outputs
xylrc = 0.5 * xylrc + 0.5 * xylrrgb
xylrc[xylrc < 6] = 0
xylrc[xylrc > 25] = 255
return xylrc
print("extracting image")
extractedImage, _ = smartextractor(image, template)
print("extracting right image")
rextractedImage, _ = smartextractor(extractedImage, rtemplate, vis=False)
grextractedImage = cv2.cvtColor(rextractedImage, cv2.COLOR_BGR2GRAY)
bfsobelImg = Sobel(rextractedImage)
sobelImg = Sobel(rextractedImage, bilateralFilter=False)
csobelImg = cv2.add(bfsobelImg, sobelImg)
csobelImg[csobelImg < 6] = 0
csobelImg[csobelImg > 18] = 255
csobelImg = csobelImg.astype(np.uint8)
img2 = csobelImg.copy()
ret, thresh = cv2.threshold(img2, 18, 255, 0)
contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
contours = sorted(contours, key=cv2.contourArea, reverse=True)
count = 0
trigger = False
for c in contours:
# approximate the contour
peri = cv2.arcLength(c, True)
contours[count] = cv2.approxPolyDP(c, 0.05 * peri, True)
if len(contours[count]) == 4:
if trigger is False:
screenCnt = contours[count]
trigger = True
count += 1
tl = screenCnt[0]
tr = screenCnt[1]
bl = screenCnt[3]
br = screenCnt[2]
tLy, tLx = tl[0]
tRy, tRx = tr[0]
bLy, bLx = bl[0]
bRy, bRx = br[0]
ratio = .15
realSpace = (3/16)
boxwidth = int(((tRx - tLx) + (bRx - bLx))*.5 - (tLx + bLx)*.5)
boxheight = int(((bRy - tRy) + (bLy - tLy))*.5 - (tRy + tLy)*.5)
spaceWidth = int((boxwidth + boxheight)*.5*realSpace)
boxcenter = [int(((bRy - tRy)*.5 + (bLy - tLy)*.5)*.5), int(((tRx - tLx)*.5 + (bRx - bLx)*.5)*.5)]
roitl = [boxcenter[0] - int(ratio*boxheight), boxcenter[1] - int(ratio*boxwidth)]
roitr = [boxcenter[0] - int(ratio*boxheight), boxcenter[1] + int(ratio*boxwidth)]
roibl = [boxcenter[0] + int(ratio*boxheight), boxcenter[1] - int(ratio*boxwidth)]
roibr = [boxcenter[0] + int(ratio*boxheight), boxcenter[1] + int(ratio*boxwidth)]
spacing = int((boxwidth + boxheight)*.5)+spaceWidth
roiWhite = np.array((roitl, roitr, roibr, roibl))
roiGray = np.array(([roitl[1], roitl[0]+spacing*1], [roitr[1], roitr[0]+spacing*1],
[roibr[1], roibr[0]+spacing*1], [roibl[1], roibl[0]+spacing*1]))
roiBlack = np.array(([roitl[1], roitl[0]+spacing*6], [roitr[1], roitr[0]+spacing*6],
[roibr[1], roibr[0]+spacing*6], [roibl[1], roibl[0]+spacing*6]))
whiteAvgb, whiteAvgg, whiteAvgr, _ = cv2.mean(rextractedImage[(roitl[0]+spacing*0):(roibr[0]+spacing*0),
roitl[1]:roibr[1]])
grayAvgb, grayAvgg, grayAvgr, _ = cv2.mean(rextractedImage[(roitl[0]+spacing*1):(roibr[0]+spacing*1),
roitl[1]:roibr[1]])
blackAvgb, blackAvgg, blackAvgr, _ = cv2.mean(rextractedImage[(roitl[0]+spacing*6):(roibr[0]+spacing*6),
roitl[1]:roibr[1]])
whiteROI = rextractedImage[(roitl[0]+spacing*0):(roibr[0]+spacing*0), roitl[1]:roibr[1]]
grayROI = rextractedImage[(roitl[0]+spacing*1):(roibr[0]+spacing*1), roitl[1]:roibr[1]]
blackROI = rextractedImage[(roitl[0]+spacing*6):(roibr[0]+spacing*6), roitl[1]:roibr[1]]
imageList = [whiteROI, grayROI, blackROI]
show_images(imageList, cols=1)
correctedImage = rextractedImage.copy()
whiteROI[:, :, 0] = whiteAvgb
whiteROI[:, :, 1] = whiteAvgg
whiteROI[:, :, 2] = whiteAvgr
grayROI[:, :, 0] = grayAvgb
grayROI[:, :, 1] = grayAvgg
grayROI[:, :, 2] = grayAvgr
blackROI[:, :, 0] = blackAvgb
blackROI[:, :, 1] = blackAvgg
blackROI[:, :, 2] = blackAvgr
imageList = [whiteROI, grayROI, blackROI]
show_images(imageList, cols=1)
# SPYDER COLOR CHECKR Values: http://www.bartneck.de/2017/10/24/patch-color-definitions-for-datacolor-spydercheckr-48/
blank = np.zeros_like(csobelImg)
maskedImg = blank.copy()
maskedImg = cv2.fillConvexPoly(maskedImg, roiWhite, 255)
maskedImg = cv2.fillConvexPoly(maskedImg, roiGray, 255)
maskedImg = cv2.fillConvexPoly(maskedImg, roiBlack, 255)
res = cv2.bitwise_and(rextractedImage, rextractedImage, mask=maskedImg)
# maskedImg = cv2.fillConvexPoly(maskedImg, roi2Black, 255)
cv2.drawContours(blank, contours, -1, 255, 3)
outputSquare = np.zeros_like(csobelImg)
cv2.drawContours(outputSquare, [screenCnt], -1, 255, 3)
imageList = [rextractedImage, grextractedImage, bfsobelImg, sobelImg, csobelImg, blank, outputSquare, maskedImg, res]
show_images(imageList, cols=3)
sys.exit()
Given the RGB value of a white patch, the image can be corrected for white balance by dividing by that value. That is, applying a linear transformation that makes the white patch have the same level in the three channels:
lum = (whiteR + whiteG + whiteB)/3
imgR = imgR * lum / whiteR
imgG = imgG * lum / whiteG
imgB = imgB * lum / whiteB
Multiplying by lum makes it so that the average intensity doesn’t change.
(The computation of lum will be better if using proper weights: 0.2126, 0.7152, 0.0722, but I wanted to keep it simple. This would only make a big difference if the input white is way off the mark, in which case you'll have other issues too.)
Note that this transformation is best applied in linear RGB space. Both the image and the RGB values for white should first be converted to linear RGB if the image is stored in sRGB or similar (a raw image from the camera would be linear RGB, a JPEG would be sRGB). See here for the relevant equations.
For better precision, you can apply the above using also the RGB values of the grey patch. Take the average multiplication factor (whiteR/lum) derived from the white and grey patches, for each channel, and apply those to the image.
The black level could be subtracted from the image, prior to determining the white RGB values and correcting for white balance. This will improve contrast and color perception, but not part of white balancing.
A full color correction is way more complex, I will not go into that.

Reading a Meter using OpenCV

I am trying to read values on my electricity meter LCD display using opencv, From my picture I am able to find meter using HoughCircles method, I am able to find LCD display on meter using contours, the lcd display isn't so clear so again I search for contours to extract digits from display. Now I am unable to read values on the display using tesseract or ssocr, how can i read the values on LCD display. I just started using opencv (Beginner), don't know the right way to go from here and if my approach is correct, would appreciate any help. Below is my code snippet and the meter images links are in comments.
def process_image(path, index):
img = cv2.imread(path)
img = cv2.resize(img,(0,0),fx=2.0,fy=2.0)
height, width, depth = img.shape
print("\n---------------------------------------------\n")
print("In Process Image Path is %s height is %d Width is %d depth is %d" %(path, height, width, depth))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 15)
circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT,1.2,100)
# ensure at least one circles is found, which is our meter
if circles is not None:
circles = np.uint16(np.around(circles))
print("Meter Found")
for i in circles[0]:
CenterX = i[0]
CenterY = i[1]
Radius = i[2]
circle_img = np.zeros((height, width), np.uint8)
cv2.circle(circle_img, (CenterX, CenterY), Radius, 1, thickness=-1)
masked_data = cv2.bitwise_and(img, img, mask=circle_img)
output = masked_data.copy()
cv2.circle(output, (i[0], i[1]), i[2], (0, 255, 0), 2)
cv2.circle(output, (i[0], i[1]), 2, (0, 0, 255), 3)
cv2.imwrite("output_" + str(index) + ".jpg", output)
break
gray = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray,(5,5),1)
edged = cv2.Canny(blurred, 5,10,200)
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
displayCnt = None
contour_list = []
# loop over the contours
for c in cnts:
# approximate the contour
peri = 0.02 * cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c,peri, True)
# if the contour has four vertices, then we have found
# the meter display
if len(approx) == 4:
contour_list.append(c)
cv2.contourArea(c)
displayCnt = approx
break
warped = four_point_transform(gray, displayCnt.reshape(4, 2))
output = four_point_transform(output, displayCnt.reshape(4, 2))
thresh = cv2.adaptiveThreshold(warped, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 31, 2)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
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 > 5 and w < 100) and (h >= 15 and h <= 150) :
digitCnts.append(c)
# sort the contours from left-to-right, then initialize the
# actual digits themselves
digitCnts = contours.sort_contours(digitCnts,method="left-to-right")[0]
mask = np.zeros(thresh.shape, np.uint8)
cv2.drawContours(mask, digitCnts, -80, (255, 255, 255),-1)
mask = cv2.bitwise_not(mask)
mask = cv2.resize(mask, (0, 0), fx=2.0, fy=2.0)
result = os.popen('/usr/local/bin/ssocr --number-digits=-1 -t 10 Mask.jpg')
output = result.read()
print("Output is " + output)
output = output[2:8]
return str(round(float(output) * 0.1, 1))
else:
print("Circle not Found")
print("\n---------------------------------------------\n")
return None

Resources