【代码自用】
sift_ran.py
import numpy as np
import cv2
from matplotlib import pyplot as plt
MIN_MATCH_COUNT = 4
img1p= cv2.imread('train5.jpeg')
img2p = cv2.imread('5train5.jpeg')
img1= cv2.cvtColor(img1p, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2p, cv2.COLOR_BGR2GRAY)
# Initiate SIFT detector
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m, n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
if len(good)>MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()
h,w = img1.shape
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)
# plt.subplot(121)
# plt.imshow(img2)
img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA)
# 校正后的图像
imgOut = cv2.warpPerspective(img2p, M, (img1.shape[1], img1.shape[0]), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
plt.subplot(121)
cv2.imwrite("imgOut.jpg",imgOut)
plt.imshow(imgOut)
plt.title('imgOut')
else:
print("Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT))
matchesMask = None
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
singlePointColor = None,
matchesMask = matchesMask, # draw only inliers
flags = 2)
# 对应关键点连接图
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.subplot(122)
plt.imshow(img3, 'gray')
plt.title('target<------>original picture')
plt.show()
0new_mian.py
import os
from PIL import Image
import cv2
import cv2 as cv
import numpy as np
from nsingle_numeracy_2 import zhizhen
from matplotlib import pyplot as plt
'''#1图像预处理'''
import numpy as np
import cv2
'''#4单表盘读数:剪掉圆盘区域再角点'''
# def dushu_2(img,x1,y1,r,x2,y2)
# # 绘制扇形 1.目标图片 2.椭圆圆心 3.长短轴长度 4.偏转角度 5.圆弧起始角度 6.终止角度 7.颜色 8.是否填充
# cv2.ellipse(img, (x1, y1), (r, r), 36, 0, 36, (255, 255, 0), -1)
def dushu(x1,y1,x2,y2):
print("开始读数!")
if x1 == x2:
n =0
result = 90
elif y1 == y2 and x1<x2:
n=2
result=0
elif y1 == y2 and x1 > x2:
n = 7
result = 180
else:
k = -(y2 - y1) / (x2 - x1)
# 求反正切,再将得到的弧度转换为度
result = np.arctan(k) * 57.29577
# 234象限
if x1 > x2 and y1 > y2:
result += 180
elif x1 > x2 and y1 < y2:
result += 180
elif x1 < x2 and y1 < y2:
result += 360
if 54<result<=90 :
n=0
elif 18<result<=54 :
n = 1
elif 0<=result<=18 or 360>=result>342:
n = 2
elif 306<result<=342 :
n = 3
elif 270<result<=306 :
n = 4
elif 234<result<=270 :
n = 5
elif 198<result<=234 :
n = 6
elif 162<result<=198 :
n = 7
elif 126<result<=162 :
n = 8
elif 90<result<=126:
n = 9
else:
print("读数发生错误!")
print("直线倾斜角度为:" + str(result) + "度,读数为", n) # 得到倾斜角度
return int(n),result
'''#3单表盘提取指针'''
def tiqu(src,a,b):
img = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV_img', img)
cv2.waitKey(0)
low_hsv = np.array([150, 43, 46])
high_hsv = np.array([180, 255, 255])
# 使用opencv的inRange函数提取颜色
mask_Red1 = cv2.inRange(img, lowerb=low_hsv, upperb=high_hsv)
# Red = cv2.bitwise_and(target, target, mask=mask)
# cv2.imshow("Red1", mask_Red1)
# cv2.waitKey(0)
low_hsv = np.array([0, 43, 46])
high_hsv = np.array([10, 255, 255])
# 使用opencv的inRange函数提取颜色
mask_Red2 = cv2.inRange( img, lowerb=low_hsv, upperb=high_hsv)
maskRed = mask_Red1 + mask_Red2
# maskRed = cv2.medianBlur(maskRed, 7) # 进行中值模糊,去噪点
# cv2.imshow("Red2", mask_Red2)
cv2.imshow('Redmask1', mask_Red1)
cv2.waitKey(0)
# 腐蚀膨胀
mask = cv2.erode(maskRed, None, iterations=3 )
# maskRed = cv2.dilate(maskRed, None, iterations=1)
cv2.imshow("Redmask2", mask)
cv2.waitKey(0)
circle = np.zeros(mask.shape[0:2], dtype="uint8") # 创建圆
j = 1
while len(mask[mask == 255]) > 5:
maskcircle = cv2.circle(circle, (a, b), j, 255, -1) # 修改填充白色
maskcircle = cv2.add(mask, np.zeros(np.shape(mask), dtype=np.uint8), mask=maskcircle)
mask = mask - maskcircle
j = j + 1
cv2.imshow("point", mask)
cv2.waitKey(0)
# # 边缘检测#调用Canny函数,指定最大和最小阈值,其中apertureSize默认为3。
# cannyimage = cv2.Canny(maskRed, 50, 100)
# cv2.imshow("Red", maskRed)
# cv2.imshow("cannyimage", cannyimage)
# cv2.waitKey(0)
## # Shi-Tomasi 算法是Harris 算法的改进,角点算法识别指针顶端
cons = []
#corners = cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance, mask, blockSize, gradientSize[,corners[, useHarrisDetector[, k]]])
con = cv2.goodFeaturesToTrack(mask ,1, 0.9, 10)
if con is not None and len(con) > 0:
for x, y in np.float32(con).reshape(-1, 2):
cons.append((x, y))
cons_img = cv2.circle(src, (int(x), int(y)), 1, (0, 0, 255))
# 输出角点
print(cons)
cv2.imshow('cons_img ', cons_img)
cv2.waitKey(0)
n, ang=dushu( a,b,cons[0][0], cons[0][1] )
# linepic = cv2.line(img, (int(cons[0][0]), int(cons[0][1])), (int(i[0]), int(i[1])), (0, 0, 255))
# # if i[0] is int:
# n, ang = dushu(i[0], i[1], cons[0][0], cons[0][1])
#
#
# cv2.imshow('linepic', linepic)
# cv2.waitKey(0)
# return (n)
return n,ang
def tiqublack(img,a,b,r):
# 使用opencv的inRange函数提取颜色
# img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# cv2.imshow('HSV_img', img)
# cv2.waitKey(0)
low_hsv = np.array([0, 0, 0])
high_hsv = np.array([180, 255, 46])
# 使用opencv的inRange函数提取颜色
mask= cv2.inRange(img, lowerb=low_hsv, upperb=high_hsv)
cv2.imshow('Blackmask1', mask)
cv2.waitKey(0)
# # 进行中值模糊,去噪点
# mask= cv2.medianBlur(mask, 9)
# 腐蚀膨胀
mask = cv2.erode(mask, None, iterations=4)
mask = cv2.dilate(mask, None, iterations=1)
cv2.imshow("Blackmask2", mask )
circle = np.zeros(mask.shape[0:2], dtype="uint8") # 创建圆
j = 1
while len(mask[mask == 255]) >5:
maskcircle = cv2.circle(circle, (a, b), j, 255, -1) # 修改填充白色
maskcircle = cv2.add(mask, np.zeros(np.shape(mask), dtype=np.uint8), mask=maskcircle)
mask = mask - maskcircle
j = j + 1
cv2.imshow("point", mask)
cv2.waitKey(0)
# q,p =np.where(mask == 255)
## # Shi-Tomasi 算法是Harris 算法的改进,角点算法识别指针顶端
cons = []
# corners = cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance, mask, blockSize, gradientSize[,corners[, useHarrisDetector[, k]]])
con = cv2.goodFeaturesToTrack(mask, 1, 0.001 , 1)
if con is not None and len(con) > 0:
for x, y in np.float32(con).reshape(-1, 2):
cons.append((x, y))
cons_img = cv2.circle(img, (int(x), int(y)), 1, (0, 0, 255))
# 输出角点
print(cons)
cv2.imshow('cons_img ', cons_img)
linepic = cv2.line(img, (int(cons[0][0]), int(cons[0][1])), (int(a), int(b)), (0, 0, 255))
cv2.imshow('linepic', linepic)
cv2.waitKey(0)
n,ang=dushu(a,b,cons[0][0], cons[0][1])
# print('q,p:',q,p)
# n, ang = dushu(a, b, q,p)
# linepic = cv2.line(img, (int(cons[0][0]), int(cons[0][1])), (int(i[0]), int(i[1])), (0, 0, 255))
# # if i[0] is int:
# n, ang = dushu(i[0], i[1], cons[0][0], cons[0][1])
#
#
# cv2.imshow('linepic', linepic)
# cv2.waitKey(0)
# return (n)
return n, ang
def dividing(img):
src = img # 读取图片
ROI = np.zeros(src.shape, np.uint8) # 创建与原图同尺寸的空numpy数组,用来保存ROI信息
# 灰度化
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
cv2.waitKey(0)
# 自适应二值化
binary= cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,19,10)#均值
#blocksize过大会导致图像细节的丢失,过小虽然保存了图像细节,增加时间
# binary2= cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,19,10)#高斯
cv2.imshow("ADAPTIVE_THRESH_MEAN_C", binary)
#cv2.imshow("ADAPTIVE_THRESH_GAUSSIAN_C", binary2)
#中值滤波
binary= cv2.medianBlur(binary, 5) # 进行中值模糊,去噪点(2、4不行)
cv2.imshow("medianBlur", binary)
# cv2.imshow("ADAPTIVE_THRESH_GAUSSIAN_C", binary2)
cv2.waitKey(0)
'''#2多表盘分割'''
circles = cv2.HoughCircles(binary, cv2.HOUGH_GRADIENT, 1, 50, param1=100, param2=1, minRadius=20, maxRadius=40)
# 根据检测到圆的信息,画出每一个圆
circles = np.uint16(np.around(circles))
n=0
x = [[] for i in range(8)]
for i in circles[0, :]:
if n<8:
x[n].append(i[0])
x[n].append(i[1])
x[n].append(i[2])#存储圆的信息
n = n + 1
# # draw the outer circle
# cv2.circle(src, (i[0], i[1]), i[2] + 1, (0, 255, 0), 2)
# # draw the center of the circle
# cv2.circle(src, (i[0], i[1]), 1, (0, 0, 255), 3)
else :
break
cv2.imshow('circle', src)
cv2.waitKey(0)
print(x)
#排序
x=np.array(x)
x=x[x[:,0].argsort()]#根据图上位置排序表盘
print(x)
n = 0
ang = [0, 0, 0, 0, 0, 0, 0, 0]
k= [0, 0, 0, 0, 0, 0, 0, 0]
for i in range(len(x)):
# draw the outer circle
circle = np.zeros(ROI.shape[0:2], dtype="uint8") # 创建圆
maskcircle = cv2.circle(circle, (x[i][0], x[i][1]), x[i][2]-2, 255, -1) # 修改填充白色
mask = cv2.add(src, np.zeros(np.shape(src), dtype=np.uint8), mask=maskcircle)
bg = np.ones_like(img, np.uint8) * 255
cv2.bitwise_not(bg, bg, mask=maskcircle) # bg的多边形区域为0,背景区域为255
cv2.imshow('bg.jpg', bg)
mask = mask + bg
cv2.imshow('result.jpg', mask)
cv2.waitKey(0)
if n >= 0 and n <= 3:
print(x[n])
ang[n],k[n]=tiqublack(mask,x[n][0],x[n][1],x[n][2])
elif 3 < n < 8:
ang[n],k[n]=tiqu(mask,x[n][0],x[n][1] )
n = n + 1
return ang,k
if __name__ == '__main__':
#img = "imgOut.jpg"
img = "train5.jpeg"#可识别
#img = "1second_template.jpg"
#img = "train6.jpeg"#可识别,刻度处有问题
#img = "train7.jpeg"
img = cv2.imread(img)
#第一步:选出ROI区域,分割成单个圆盘
ang,k=dividing(img)
x=[]
y=[]
x.extend([ang[2],ang[0],ang[1],ang[3], ang[4],ang[6],ang[7],ang[5]])
y.extend([k[2],k[0],k[1],k[3], k[4],k[6],k[7],k[5]])
print("黑色指针部分水表读数为:", ang[2], ang[0], ang[1], ang[3])
print("红色指针部分水表读数为:", ang[4], ang[6], ang[7], ang[5])
print(x,y)
99kishihua,py
```python
# # # 创建GUI窗口打开图像 并显示在窗口中
# #
# # from PIL import Image, ImageTk # 导入图像处理函数库
# # import tkinter as tk # 导入GUI界面函数库
# # # 创建窗口 设定大小并命名
# # window = tk.Tk()
# # window.title('图像显示界面')
# # window.geometry('600x500')
# # global img_png # 定义全局变量 图像的
# # var = tk.StringVar() # 这时文字变量储存器
# #
# # # 创建打开图像和显示图像函数
# # def Open_Img():
# # global img_png
# # var.set('已打开')
# # Img = Image.open('E:\\Python_3_7\\a.jpg')
# # img_png = ImageTk.PhotoImage(Img)
# #
# # def Show_Img():
# # global img_png
# # var.set('已显示') # 设置标签的文字为 'you hit me'
# # label_Img = tk.Label(window, image=img_png)
# # label_Img.pack()
# # # 创建文本窗口,显示当前操作状态
# # Label_Show = tk.Label(window,
# # textvariable=var, # 使用 textvariable 替换 text, 因为这个可以变化
# # bg='blue', font=('Arial', 12), width=15, height=2)
# # Label_Show.pack()
# # # 创建打开图像按钮
# # btn_Open = tk.Button(window,
# # text='打开图像', # 显示在按钮上的文字
# # width=15, height=2,
# # command=Open_Img) # 点击按钮式执行的命令
# # btn_Open.pack() # 按钮位置
# # # 创建显示图像按钮
# # btn_Show = tk.Button(window,
# # text='显示图像', # 显示在按钮上的文字
# # width=15, height=2,
# # command=Show_Img) # 点击按钮式执行的命令
# # btn_Show.pack() # 按钮位置
# #
# # # 运行整体窗口
# # window.mainloop()
#
#
#
#
# from tkinter import *
# from tkinter import filedialog
#
# window = Tk()
# window.title("亲情导出")
# window.geometry('400x300')
# import tkinter.filedialog
#
# e1 = Label(window, text="路径:") # 这是标签
# e1.grid(row=1, column=0)
# g = Entry(window, width=40) # 这是输入框
# g.grid(row=1, column=1, columnspan=1)
#
#
# def se(): # 这是获取路径函数
# g.delete(0, "end")
# path = filedialog.askopenfilename()
# path = path.replace("/", "\\\\") # 通过replace函数替换绝对文件地址中的/来使文件可被程序读取 #注意:\\转义后为\,所以\\\\转义后为\\
# g.insert('insert', path)
#
#
# b1 = Button(window, text="查询", command=se) # 这是按键
# b1.grid(row=1, column=3)
#
# window.mainloop()
import cv2
from lunwen_000 import dividing
from tkinter import *
from tkinter.filedialog import askopenfilename
# from tkinter.messagebox import showinfo
frameT = Tk()
frameT.geometry('500x200+400+200')
frameT.title('选择需要输入处理的文件')
frame = Frame(frameT)
frame.pack(padx=10, pady=10) # 设置外边距
frame_1 = Frame(frameT)
frame_1.pack(padx=10, pady=10) # 设置外边距
frame1 = Frame(frameT)
frame1.pack(padx=10, pady=10)
v1 = StringVar()
v2 = StringVar()
ent = Entry(frame, width=50, textvariable=v1).pack(fill=X, side=LEFT) # x方向填充,靠左
ent = Entry(frame_1, width=50, textvariable=v2).pack(fill=X, side=LEFT) # x方向填充,靠左
global i,num
def fileopen():
file_sql = askopenfilename()
print(file_sql)
global i
i=file_sql
if file_sql:
v1.set(file_sql)
def number():
# img = "train5.jpeg"#可识别
# img = "1second_template.jpg"
# img = "train6.jpeg"
# img = "train7.jpeg"
global i,num
img = cv2.imread(i)
# 第一步:选出ROI区域,分割成单个圆盘
ang = dividing(img)
print("黑色指针部分水表读数为:", ang[2], ang[0], ang[1], ang[3])
print("红色指针部分水表读数为:", ang[4], ang[6], ang[7], ang[5])
num = 1000 * ang[2] + 100 * ang[0] + 10 * ang[1] + 1 * ang[3] + 0.1 * ang[4] + 0.01 * ang[6] + 0.001 * ang[
7] + 0.0001 * ang[5]
if num:
v2.set(num)
cv2.destroyAllWindows()
btn = Button(frame, width=20, text='总文件', font=("宋体", 14), command=fileopen).pack(fil=X, padx=10)
# btn_1 = Button(frame_1, width=20, text='匹配文件', font=("宋体", 14), command=fileopen_1).pack(fil=X, padx=10)
ext = Button(frame1, width=10, text='退出', font=("宋体", 14), command=frameT.quit).pack(fill=X, side=LEFT)
etb = Button(frame_1, width=10, text='读数', font=("宋体", 14), command=number).pack(fill=X, padx=10)
frameT.mainloop()