实习内容

代码

# -*- coding:utf-8 -*-
# 背景检测
import cv2

# 这里修改要检测图像的路径
img = cv2.imread('C:/Users/simao.wang.HIRAIN/Desktop/test05.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)


def mouse_click(event, x, y, flags, para):
    if event == cv2.EVENT_LBUTTONDOWN:  # 左边鼠标点击
        # print('PIX:', x, y)
        print("BGR:", img[y, x])
        print("GRAY:", gray[y, x])
        # print("HSV:", hsv[y, x])


if __name__ == '__main__':
    cv2.namedWindow("img")
    cv2.setMouseCallback("img", mouse_click)
    while True:
        cv2.imshow('img', img)
        if cv2.waitKey() == ord('q'):
            break
    cv2.destroyAllWindows()

#模板匹配和背景灯检测——原始
import cv2
import numpy as np


print(cv2.__version__)  # 3.4.2

# 1.模板匹配
#这里是输入的目标图像
img = cv2.imread('C:/Users/simao.wang.HIRAIN/Desktop/task01.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #转换为灰度图
print(img_gray.shape)  # 显示目标大小

#这里是输入的模板图像
template = cv2.imread('C:/Users/simao.wang.HIRAIN/Desktop/task01-1.jpg', 0)
print(template.shape)  # 显示模板大小
h, w = template.shape[:2]  # rows->h, cols->w

# 6种匹配方法
# methods = [cv2.TM_CCOEFF,  相关匹配
#            cv2.TM_CCOEFF_NORMED,  标准相关匹配
#            cv2.TM_CCORR,
#            cv2.TM_CCORR_NORMED,
#            cv2.TM_SQDIFF,
#            cv2.TM_SQDIFF_NORMED]
#相似度度量指标
# 差值平方和匹配 CV_TM_SQDIFF 原理:计算模板与某个子图的对应像素的差值平方和。越相似该值越小
# 标准化差值平方和匹配 CV_TM_SQDIFF_NORMED 原理:这种标准化操作可以保证当模板和图像各个像素的亮度都乘上了同一个系数时,相关度不发生变化。越相似该值越小
# 相关匹配 CV_TM_CCORR 原理:模板与子图对应位置相乘,可以将其看作是差值平方和平方项展开之后中间的那个2ab项。越相似该值越大
# 标准相关匹配 CV_TM_CCORR_NORMED 原理:和标准化差值平方和匹配类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。越相似该值越大
# 相关匹配 CV_TM_CCOEFF 原理:把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量。越相似该值越大
# 标准相关匹配 CV_TM_CCOEFF_NORMED 原理:在减去了各自的平均值之外,还要各自除以各自的方差。经过减去平均值和除以方差这么两步操作之后,无论是我们的目标图像还是模板都被标准化了,这样可以保证图像和模板分别改变光照不影响计算结果。越相似该值越大

#这里选取了两种算法作为模板匹配的方法
methods = [cv2.TM_CCOEFF_NORMED,
           cv2.TM_SQDIFF_NORMED]

for meth in methods:
    img2 = img.copy()

    res = cv2.matchTemplate(img_gray, template, meth) #求出模板与目标图像匹配得到的矩阵结果
    print(res.shape) #矩阵的大小

    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) #求出这个矩阵的最小值,最大值,并得到最大值,最小值的索引

    # 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值
    if meth in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc

    bottom_right = (top_left[0] + w, top_left[1] + h) #画框的右下坐标

    #显示出模板中心点的灰度值,用于检测背景灯的亮度读数
    x=int(top_left[0] + w/2) #模板中心点的x坐标
    y=int(top_left[1] + h/2) #模板中心点的y坐标
    print(x,y) #模板中心点坐标
    print("GRAY:", img_gray[y, x]) #模板中心点的灰度值

    # 在匹配点即模板左上角画小圆心
    cv2.circle(res, top_left, 10, 0, 2)
    cv2.namedWindow('res',cv2.WINDOW_FREERATIO)
    cv2.imshow("res", res)

    # 画矩形,框出模板在目标图像中的位置
    cv2.rectangle(img2, top_left, bottom_right, (0, 255, 0), 2)
    cv2.namedWindow('img2', cv2.WINDOW_FREERATIO)
    cv2.imshow("img2", img2)
    cv2.waitKey(0)

#相似度度量指标
# 差值平方和匹配 CV_TM_SQDIFF 原理:计算模板与某个子图的对应像素的差值平方和。越相似该值越小
# 标准化差值平方和匹配 CV_TM_SQDIFF_NORMED 原理:这种标准化操作可以保证当模板和图像各个像素的亮度都乘上了同一个系数时,相关度不发生变化。越相似该值越小
# 相关匹配 CV_TM_CCORR 原理:模板与子图对应位置相乘,可以将其看作是差值平方和平方项展开之后中间的那个2ab项。越相似该值越大
# 标准相关匹配 CV_TM_CCORR_NORMED 原理:和标准化差值平方和匹配类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。越相似该值越大
# 相关匹配 CV_TM_CCOEFF 原理:把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量。越相似该值越大
# 标准相关匹配 CV_TM_CCOEFF_NORMED 原理:在减去了各自的平均值之外,还要各自除以各自的方差。经过减去平均值和除以方差这么两步操作之后,无论是我们的目标图像还是模板都被标准化了,这样可以保证图像和模板分别改变光照不影响计算结果。越相似该值越大
# 基于FLANN的匹配器(FLANN based Matcher)定位图片,只有opencv版本低于3.4.2.16才能使用SIFT特征点匹配方法
import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_MATCH_COUNT = 7  # 设置最低特征点匹配数量为7,如果找到的特征点数大于这个值,那么就匹配成功并框出在目标图像上匹配到的模板位置
template = cv2.imread('C:/Users/simao.wang.HIRAIN/Desktop/Demotemp.jpg', 0)  # 模板图像,需要人为输入
target = cv2.imread('C:/Users/simao.wang.HIRAIN/Desktop/Demo.jpg', 0)  # 输入的目标图像,目的是为了找到模板图像在目标图像中的位置
# 创建sift(尺度不变特征变换匹配算法)检测器
sift = cv2.xfeatures2d.SIFT_create()
# 在模板图像和目标图像中分别提取特征点
kp1, des1 = sift.detectAndCompute(template, None)
kp2, des2 = sift.detectAndCompute(target, None)
# 创建设置FLANN快速最近邻逼近搜索匹配
# KDtree建立索引方式的常量参数
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50) #checks指定索引树要被遍历的次数为50
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2) #进行匹配搜索
# 寻找距离近的特征点放入列表
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)
    # 计算变换矩阵和MASK
    M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
    matchesMask = mask.ravel().tolist()
    h, w = template.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)
    cv2.polylines(target, [np.int32(dst)], True, 0, 2, cv2.LINE_AA)
else:
    print("Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT))
    matchesMask = None
draw_params = dict(matchColor=(0, 255, 0),
                   singlePointColor=None,
                   matchesMask=matchesMask,
                   flags=2)
result = cv2.drawMatches(template, kp1, target, kp2, good, None, **draw_params)
plt.imshow(result, 'gray')
plt.show()

#SIFT原理:
# 1.通过一个变化尺度的高斯函数对图像进行尺度空间变换,小尺度对应于图像的细节特征,大尺度对应于图像的概貌特征(尺度空间)
# 2.建立高斯图像金字塔和DOG高斯差分金字塔。可以通过高斯差分图像(DOG在计算上只需相邻高斯平滑后图像相减)看出图像上的像素值变化情况。(如果没有变化,也就没有特征。特征必须是变化尽可能多的点。)DOG图像描绘的是目标的轮廓。
# 3.局部极值检测。中间的检测点和它同尺度的8个相邻点和上下相邻尺度对应的9×2个 点共26个点比较,以确保在尺度空间和二维图像空间都检测到极值点。
# 4.去除边缘效应,实现关键的的精确定位
# 5.关键点主方向分配  关键点主方向分配就是基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,使得描述符具有旋转不变性。
# 6.用一组向量描述关键点的特征,每一个关键点,拥有三个信息:位置、尺度以及方向
# 7.利用欧氏距离算出模板和目标图像之间的特征关键点距离,距离越小说明相似度越高。关键点匹配采用Kd树(平衡二叉树)来完成搜索,以目标图像的关键点为基准,搜索与目标图像的特征点最邻近的原图像特征点和次邻近的原图像特征点
# 指针读数
import cv2
import numpy as np


def avg_circles(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


def dist_2_pts(x1, y1, x2, y2):
    return np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)


def calibrate_gauge(gauge_number, file_type,img):
    '''
        This function should be run using a test image in order to calibrate the range available to the dial as well as the
        units.  It works by first finding the center point and radius of the gauge.  Then it draws lines at hard coded intervals
        (separation) in degrees.  It then prompts the user to enter position in degrees of the lowest possible value of the gauge,
        as well as the starting value (which is probably zero in most cases but it won't assume that).  It will then ask for the
        position in degrees of the largest possible value of the gauge. Finally, it will ask for the units.  This assumes that
        the gauge is linear (as most probably are).
        It will return the min value with angle in degrees (as a tuple), the max value with angle in degree45s (as a tuple),
        and the units (as a string).
        这个函数用测试图片来校准刻度盘和刻度盘可用的范围单位。需要之前所得的中心点以及半径。然后绘制出刻度。
        需要输入表盘读数最小角度,最大角度,最小值,最大值,以及单位(min_angle,max_angle,min_value,max_value,units)
    '''
    height, width = img.shape[:2]
    # 将图片转为灰度图片
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # convert to gray

    # 霍夫圆环检测
    # image:8位,单通道图像
    # method:定义检测图像中圆的方法。目前唯一实现的方法cv2.HOUGH_GRADIENT。

    # dp:累加器分辨率与图像分辨率的反比。dp获取越大,累加器数组越小。
    # minDist:检测到的圆的中心,(x,y)坐标之间的最小距离。如果minDist太小,则可能导致检测到多个相邻的圆。如果minDist太大,则可能导致很多圆检测不到。
    # param1:用于处理边缘检测的梯度值方法。
    # param2:cv2.HOUGH_GRADIENT方法的累加器阈值。阈值越小,检测到的圈子越多。
    # minRadius:半径的最小大小(以像素为单位)。
    # maxRadius:半径的最大大小(以像素为单位)。

    circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, np.array([]), 100, 50, int(height * 0.4),
                               int(height * 0.5))

    a, b, c = circles.shape
    # 获取圆的坐标x,y和半径r
    x, y, r = avg_circles(circles, b)

    cv2.circle(img, (x, y), r, (0, 0, 255), 3, cv2.LINE_AA)  # 用红色画圆
    cv2.circle(img, (x, y), 2, (0, 255, 0), 3, cv2.LINE_AA)  # 画圆心

    # for testing, output circles on image
    # cv2.imwrite('gauge-%s-circles.%s' % (gauge_number, file_type), img)

    # for calibration, plot lines from center going out at every 10 degrees and add marker
    # for i from 0 to 36 (every 10 deg)

    '''
    goes through the motion of a circle and sets x and y values based on the set separation spacing.  Also adds text to each
    line.  These lines and text labels serve as the reference point for the user to enter
    NOTE: by default this approach sets 0/360 to be the +x axis (if the image has a cartesian grid in the middle), the addition
    (i+9) in the text offset rotates the labels by 90 degrees so 0/360 is at the bottom (-y in cartesian).  So this assumes the
    gauge is aligned in the image, but it can be adjusted by changing the value of 9 to something else.
    根据画出的刻度值,给定x,y的值,并在此位置添加文本信息。
    这些刻度和文本标签用作用户输入的参考点

    '''
    separation = 5.0  # 每格刻度的度数值
    interval = int(360 / separation)
    p1 = np.zeros((interval, 2))  # set empty arrays
    p2 = np.zeros((interval, 2))
    p_text = np.zeros((interval, 2))
    for i in ran
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值