Opencv 如何使用Open CV读取模拟仪表
我对尝试使用树莓圆周率和开放式CV读取模拟量表感兴趣。我只在opencv中真正搞砸了人脸检测,所以我甚至不知道从哪里开始。有什么想法,起点吗?您可以使用HoughCircles方法检测圆,并使用Python中opencv库的HoughLinesP方法检测线。在检测到这些之后,您可以通过三角法从测线位置找出量规的值。 您可以看到python中的示例代码。它基本上是这样做的:Opencv 如何使用Open CV读取模拟仪表,opencv,raspberry-pi,detect,Opencv,Raspberry Pi,Detect,我对尝试使用树莓圆周率和开放式CV读取模拟量表感兴趣。我只在opencv中真正搞砸了人脸检测,所以我甚至不知道从哪里开始。有什么想法,起点吗?您可以使用HoughCircles方法检测圆,并使用Python中opencv库的HoughLinesP方法检测线。在检测到这些之后,您可以通过三角法从测线位置找出量规的值。 您可以看到python中的示例代码。它基本上是这样做的: 用imread方法读取图像 用cvtColor将其变成灰色 用HoughCircles找出圆的中心x、y坐标和半径,这些方
- 用imread方法读取图像
- 用cvtColor将其变成灰色
- 用HoughCircles找出圆的中心x、y坐标和半径,这些方法有一些参数可以调整
- 再次使用HoughLinesP方法检测线。应调整参数
- 计算该值,考虑量规上的最大值、最小值和量规的角度间隔
导入操作系统
进口cv2
进口numpy
def getScriptDir():
currentFile=uuuu file_u35;可以是“我的脚本”或“/myu脚本”或
realPath=os.path.realPath(当前文件)#/home/user/test/my_script.py
dirPath=os.path.dirname(realPath)
返回路径
def getUserRealGaugeDetails():
最小角度=输入(“最小角度:”)#可能的最小角度
最大角度=输入(“最大角度”)#最大可能角度
最小值=输入(“最小值:”)#通常为零
最大值=输入('max deger:')#仪表的最大读数
单位=输入('Birim girin:')
返回最小角度、最大角度、最小值、最大值、单位
def SETSTATICUSERREALGAGEDETAILS():
最小角度=5#输入(“最小角度(刻度盘的最小可能角度)-以度为单位:”)#最小可能角度
最大角度=355#输入(“最大角度(最大可能角度)-以度为单位:”)#最大可能角度
最小值=-20#输入(“最小值:”)#通常为零
最大值=120#输入(“最大值”)#仪表的最大读数
单位='b'#输入('输入单位:')
返回最小角度、最大角度、最小值、最大值、单位
def getImage():
dirPath=getScriptDir()
dirPath+=“/images/1.jpg”
返回cv2.imread(dirPath)
def距离2点(x1、y1、x2、y2):
#打印np.sqrt((x2-x1)^2+(y2-y1)^2)
返回numpy.sqrt((x2-x1)**2+(y2-y1)**2)
def平均圆(圆,b):
平均值x=0
平均值y=0
平均值=0
对于范围(b)中的i:
#可选-多个圆的平均值(当仪表处于微小角度时可能发生)
平均值=平均值+圆圈[0][i][0]
平均值=平均值+圆[0][i][1]
平均值=平均值+圆圈[0][i][2]
平均x=int(平均x/(b))
平均值y=int(平均值y/(b))
平均r=int(平均r/(b))
返回平均值x,平均值y,平均值r
#返回圆的圆心和半径
def getCircleAndCustomize(图像):
高度,宽度=图像。形状[:2]
gray=cv2.CVT颜色(图像,cv2.COLOR_BGR2GRAY)#转换为灰色
#灰色=cv2.高斯模糊(灰色,(5,5,0)
#灰色=cv2.medianBlur(灰色,5)
#cv2.imwrite('C:/Users/okarademirci/Desktop/analog gauge reader/images/gauge-gray-2.jpg',灰色)
#检测圆
#将搜索限制在可能半径的35-48%范围内,可以在不同样本中获得相当好的结果。记得吗
#这些是对应于可能半径搜索范围的像素值。
圆=cv2.HoughCircles(灰色,cv2.HOUGH_渐变,1,20,numpy.数组([]),100,50,整数(高度*0.35),整数(高度*0.48))
#坐标和半径
a、 b,c=圆形
x、 y,r=平均圆(圆,b)
返回x,y,r
def get_当前_值(img、最小_角、最大_角、最小_值、最大_值、x、y、r):
gray2=cv2.CVT颜色(img,cv2.COLOR\u BGR2GRAY)
#设置阈值和最大值
thresh=175
最大值=255
#出于测试目的,发现cv2.THRESH_BINARY_INV性能最佳
#th,dst1=cv2.阈值(灰度2,阈值,最大值,cv2.阈值二进制);
#th,dst2=cv2.阈值(灰度2,阈值,最大值,cv2.阈值二进制INV);
#th,dst3=cv2.阈值(灰度2,阈值,最大值,cv2.阈值);
#th,dst4=cv2.阈值(灰度2,阈值,最大值,cv2.阈值为零);
#th,dst5=cv2.阈值(灰度2,阈值,最大值,cv2.阈值到零值);
#cv2.imwrite('仪表-%s-dst1.%s'(仪表号,文件类型),dst1)
#cv2.imwrite('仪表-%s-dst2.%s'(仪表号,文件类型),dst2)
#cv2.imwrite('仪表-%s-dst3.%s'(仪表号,文件类型),dst3)
#cv2.imwrite('仪表-%s-dst4.%s'(仪表号,文件类型),dst4)
#cv2.imwrite('仪表-%s-dst5.%s'(仪表号,文件类型),dst5)
#应用有助于查找线的阈值
th,dst2=cv2.阈值(灰度2,阈值,最大值,cv2.阈值二进制值)
#发现Hough线通常在不使用Canny/blurring的情况下表现更好,但也有一些例外,它只适用于Canny/blurring
#dst2=cv2.medianBlur(dst2,5)
#dst2=cv2.Canny(dst2,50,150)
#dst2=cv2.GaussianBlur(dst2,(5,5,0)
#对于测试,显示阈值化后的图像
dirPath=getScriptDir()+'/images/posterreshold.jpg'
cv2.imwrite(dirPath,dst2)
#找线
minLineLength=10
maxLineGap=0
lines=cv2.HoughLinesP(image=dst2,rho=3,theta=numpy.pi/180,threshold=100,minLineLength=minLineLength,maxLineGap=0)#rho设置为3以检测更多的线,更容易获取更多线,然后稍后过滤掉它们
#出于测试目的,显示所有找到的行
#对于范围(0,len(行))中的i:
#对于[i]行中的x1、y1、x2、y2:
#cv2.线(img,(x1,y1),(x2,y2),(0255,0),2)
#cv2.imwrite('gauge-%s-lines-test.%s'(gauge\u编号,文件类型),img)
#删除给定半径以外的所有线
最后一行列表=[]
#打印“半径:%s”%r
diff1LowerBound=0.15#diff1LowerBound和diff1UpperBound确定直线与中心的距离
diff1UpperBound=0.25
diff2LowerBoun
import os
import cv2
import numpy
def getScriptDir():
currentFile = __file__ # May be 'my_script', or './my_script' or
realPath = os.path.realpath(currentFile) # /home/user/test/my_script.py
dirPath = os.path.dirname(realPath)
return dirPath
def getUserRealGaugeDetails():
min_angle = input('Min derece: ') #the lowest possible angle
max_angle = input('Max derece ') #highest possible angle
min_value = input('Min deger: ') #usually zero
max_value = input('Max deger: ') #maximum reading of the gauge
units = input('Birim girin: ')
return min_angle,max_angle,min_value,max_value,units
def setStaticUserRealGaugeDetails():
min_angle = 5 # input('Min angle (lowest possible angle of dial) - in degrees: ') #the lowest possible angle
max_angle = 355 # input('Max angle (highest possible angle) - in degrees: ') #highest possible angle
min_value = -20 #input('Min value: ') #usually zero
max_value = 120 #input('Max value: ') #maximum reading of the gauge
units = 'b' #input('Enter units: ')
return min_angle,max_angle,min_value,max_value,units
def getImage():
dirPath = getScriptDir()
dirPath += "/images/1.jpg"
return cv2.imread(dirPath)
def distance2Points(x1, y1, x2, y2):
#print np.sqrt((x2-x1)^2+(y2-y1)^2)
return numpy.sqrt((x2 - x1)**2 + (y2 - y1)**2)
def averageCircle(circles, b):
avg_x=0
avg_y=0
avg_r=0
for i in range(b):
#optional - average for multiple circles (can happen when a gauge is at a slight angle)
avg_x = avg_x + circles[0][i][0]
avg_y = avg_y + circles[0][i][1]
avg_r = avg_r + circles[0][i][2]
avg_x = int(avg_x/(b))
avg_y = int(avg_y/(b))
avg_r = int(avg_r/(b))
return avg_x, avg_y, avg_r
#return the center and radius of the circle
def getCircleAndCustomize(image):
height, width = image.shape[:2]
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #convert to gray
# gray = cv2.GaussianBlur(gray, (5, 5), 0)
# gray = cv2.medianBlur(gray, 5)
# cv2.imwrite('C:/Users/okarademirci/Desktop/analog-gauge-reader/images/gauge-gray-2.jpg', gray)
#detect circles
#restricting the search from 35-48% of the possible radii gives fairly good results across different samples. Remember that
#these are pixel values which correspond to the possible radii search range.
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, numpy.array([]), 100, 50, int(height*0.35), int(height*0.48))
#coordinates and radius
a, b, c = circles.shape
x,y,r = averageCircle(circles, b)
return x ,y ,r
def get_current_value(img, min_angle, max_angle, min_value, max_value, x, y, r):
gray2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Set threshold and maxValue
thresh = 175
maxValue = 255
# for testing purposes, found cv2.THRESH_BINARY_INV to perform the best
# th, dst1 = cv2.threshold(gray2, thresh, maxValue, cv2.THRESH_BINARY);
# th, dst2 = cv2.threshold(gray2, thresh, maxValue, cv2.THRESH_BINARY_INV);
# th, dst3 = cv2.threshold(gray2, thresh, maxValue, cv2.THRESH_TRUNC);
# th, dst4 = cv2.threshold(gray2, thresh, maxValue, cv2.THRESH_TOZERO);
# th, dst5 = cv2.threshold(gray2, thresh, maxValue, cv2.THRESH_TOZERO_INV);
# cv2.imwrite('gauge-%s-dst1.%s' % (gauge_number, file_type), dst1)
# cv2.imwrite('gauge-%s-dst2.%s' % (gauge_number, file_type), dst2)
# cv2.imwrite('gauge-%s-dst3.%s' % (gauge_number, file_type), dst3)
# cv2.imwrite('gauge-%s-dst4.%s' % (gauge_number, file_type), dst4)
# cv2.imwrite('gauge-%s-dst5.%s' % (gauge_number, file_type), dst5)
# apply thresholding which helps for finding lines
th, dst2 = cv2.threshold(gray2, thresh, maxValue, cv2.THRESH_BINARY_INV)
# found Hough Lines generally performs better without Canny / blurring, though there were a couple exceptions where it would only work with Canny / blurring
#dst2 = cv2.medianBlur(dst2, 5)
#dst2 = cv2.Canny(dst2, 50, 150)
#dst2 = cv2.GaussianBlur(dst2, (5, 5), 0)
# for testing, show image after thresholding
dirPath = getScriptDir() + '/images/afterTreshold.jpg'
cv2.imwrite(dirPath, dst2)
# find lines
minLineLength = 10
maxLineGap = 0
lines = cv2.HoughLinesP(image=dst2, rho=3, theta=numpy.pi / 180, threshold=100,minLineLength=minLineLength, maxLineGap=0) # rho is set to 3 to detect more lines, easier to get more then filter them out later
#for testing purposes, show all found lines
# for i in range(0, len(lines)):
# for x1, y1, x2, y2 in lines[i]:
# cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
# cv2.imwrite('gauge-%s-lines-test.%s' %(gauge_number, file_type), img)
# remove all lines outside a given radius
final_line_list = []
#print "radius: %s" %r
diff1LowerBound = 0.15 #diff1LowerBound and diff1UpperBound determine how close the line should be from the center
diff1UpperBound = 0.25
diff2LowerBound = 0.5 #diff2LowerBound and diff2UpperBound determine how close the other point of the line should be to the outside of the gauge
diff2UpperBound = 1.0
for i in range(0, len(lines)):
for x1, y1, x2, y2 in lines[i]:
diff1 = distance2Points(x, y, x1, y1) # x, y is center of circle
diff2 = distance2Points(x, y, x2, y2) # x, y is center of circle
#set diff1 to be the smaller (closest to the center) of the two), makes the math easier
if (diff1 > diff2):
temp = diff1
diff1 = diff2
diff2 = temp
# check if line is within an acceptable range
if (((diff1<diff1UpperBound*r) and (diff1>diff1LowerBound*r) and (diff2<diff2UpperBound*r)) and (diff2>diff2LowerBound*r)):
line_length = distance2Points(x1, y1, x2, y2)
# add to final list
final_line_list.append([x1, y1, x2, y2])
#testing only, show all lines after filtering
# for i in range(0,len(final_line_list)):
# x1 = final_line_list[i][0]
# y1 = final_line_list[i][1]
# x2 = final_line_list[i][2]
# y2 = final_line_list[i][3]
# cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
# assumes the first line is the best one
x1 = final_line_list[0][0]
y1 = final_line_list[0][1]
x2 = final_line_list[0][2]
y2 = final_line_list[0][3]
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
#for testing purposes, show the line overlayed on the original image
#cv2.imwrite('gauge-1-test.jpg', img)
#cv2.imwrite('C:/Users/okarademirci/Desktop/analog-gauge-reader/images/gauge-%s-lines-2.%s' % (gauge_number, file_type), img)
#find the farthest point from the center to be what is used to determine the angle
dist_pt_0 = distance2Points(x, y, x1, y1)
dist_pt_1 = distance2Points(x, y, x2, y2)
if (dist_pt_0 > dist_pt_1):
x_angle = x1 - x
y_angle = y - y1
else:
x_angle = x2 - x
y_angle = y - y2
# take the arc tan of y/x to find the angle
res = numpy.arctan(numpy.divide(float(y_angle), float(x_angle)))
#np.rad2deg(res) #coverts to degrees
# print x_angle
# print y_angle
# print res
# print np.rad2deg(res)
#these were determined by trial and error
res = numpy.rad2deg(res)
if x_angle > 0 and y_angle > 0: #in quadrant I
final_angle = 270 - res
if x_angle < 0 and y_angle > 0: #in quadrant II
final_angle = 90 - res
if x_angle < 0 and y_angle < 0: #in quadrant III
final_angle = 90 - res
if x_angle > 0 and y_angle < 0: #in quadrant IV
final_angle = 270 - res
#print final_angle
old_min = float(min_angle)
old_max = float(max_angle)
new_min = float(min_value)
new_max = float(max_value)
old_value = final_angle
old_range = (old_max - old_min)
new_range = (new_max - new_min)
new_value = (((old_value - old_min) * new_range) / old_range) + new_min
return new_value
def main():
# 1) get the image from directory.
image = getImage()
min_angle,max_angle,min_value,max_value,units = setStaticUserRealGaugeDetails()
# 2) covnert the image to gray .
# 3) find the circle in the image with customization
x,y,r = getCircleAndCustomize(image)
# 4) find the line in the circle.
# 5) find the value in the range of guage
newValue = get_current_value(image,min_angle,max_angle,min_value,max_value,x,y,r)
print(newValue)
if __name__=='__main__':
main()