模板匹配(旋转缩放)旋转不好匹配+20201019

import cv2
import numpy as np
# 加载原始RGB图像
img_rgb = cv2.imread("capture1.jpg")
# 创建一个原始图像的灰度版本,所有操作在灰度版本中处理,然后在RGB图像中使用相同坐标还原
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
# 加载将要搜索的图像模板
#模板1 筛选图案1
template1 = cv2.imread('template1.png', 0)
#模板2 3 筛选图案2
template2 = cv2.imread('template2.png', 0)
template3 = cv2.imread('template3.png', 0)
# 记录图像模板的尺寸
w1, h1 = template1.shape[::-1]
w2, h2 = template2.shape[::-1]
w3, h3 = template3.shape[::-1]

list[::-1]是将列表反过来,从序列的最后一个元素开始切片
h1,w1 = template1.shape[::1] ----------- 有啥区别???????????????

def rotate_bound(image, angle):#图片旋转但不改变大小,模板匹配中大小改变对匹配效果有影响
    (h, w) = image.shape[:2]                                          #取前两位
    (cX, cY) = (w // 2, h // 2)#//是向下取整                       #取中点x,y坐标
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])            #np.abs(x)、np.fabs(x):计算数组各元素的绝对值    
    sin = np.abs(M[0, 1])
    
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY
 
    return cv2.warpAffine(image, M, (nW, nH))

在这里插入图片描述
但是单纯的这个矩阵是在原点处进行变换的,为了能够在任意位置进行旋转变换,opencv采用了另一种方式:
在这里插入图片描述
为了构造这个矩阵,opencv提供了一个函数:cv2.getRotationMatrix2D(),这个函数需要三个参数,旋转中心,旋转角度,旋转后图像的缩放比例,比如下例:
center表示中间点的位置,-5表示逆时针旋转5度,1表示进行等比列的缩放
M是2x3的矩阵

#选出所有匹配旋转模板且不重复的图案
def make_contour(template,w,h,angle,threshold):
    rects = []
    # 模板旋转匹配
    for i in range(0, 360, angle):
        new_rotate = rotate_bound(template, i)                        #注1
        # 把图片旋转后黑色的部分填充成白色
        new_rotate[new_rotate == 0] = 255
        # 使用matchTemplate对原始灰度图像和图像模板进行匹配
        res = cv2.matchTemplate(img_gray, new_rotate, cv2.TM_CCOEFF_NORMED)
        # 设定阈值
        loc = np.where(res >= threshold)                              #注2
        #x,y坐标对调打包
        for pt in zip(*loc[::-1]):
            point = np.array([[pt[0], pt[1]], [pt[0] + w, pt[1]],
                    [pt[0], pt[1] + h], [pt[0] + w, pt[1] + h]])
            rects.append(cv2.boundingRect(point))
    #模板匹配后符合要求的所有图案数量
    length = len(rects)
    #设定阈值
    threshold = 3
    i = 0
    #如果两个图案距离在阈值范围内,则等同,然后用集合去重
    while(i<length):
        print(i)
        for j in range(length):
            if j != i:
                if np.abs(rects[j][0]-rects[i][0])<= threshold:
                    if np.abs(rects[j][1]-rects[i][1]) <= threshold:
                        rects[j] = rects[i]
        i = i+1
    return set(rects)

注1:
def rotate_bound1(image, angle):
旋转图片
param image opencv读取后的图像
param angle (逆)旋转角度
注2:
np.where()
numpy中能够返回符合某一条件的下标函数:np.where(),只不过np.where()并不接受list类型的参数。
np.where()可用于接收3个参数,用于三目运算;也可用于接收1个参数,直接返回符合要求的下标。

#在原图把匹配的模板框出来并输出坐标文档
def draw_contour(contours,color):
    count = 0
    for contour in contours:
        cv2.rectangle(img_rgb, (contour[0], contour[1]), (contour[0] + contour[2], contour[1] + contour[3]),
                             color, 1)
        cx = contour[0] + (contour[2] // 2)
        cy = contour[1] + (contour[3] // 2)
        count = count + 1
        cv2.putText(img_rgb, str(count), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 1,color, 1, 1)                                               #注1
        with open("data.txt", "a+") as f:                    #注2
            f.write("contour" + '\t' + str(count) + '\t' + 'cx: ' + str(cx) + '  \t' + 'cy: ' + str(cy) + '\n')
            # 显示图像
    cv2.imwrite("after.png", img_rgb)

注1:
cv2.putText(img, str(i), (123,456)), font, 2, (0,255,0), 3)
各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细
注2:
with…as语句是简化版的try except finally语句
1.as可以省略 2. 有一个句块要执行
从文件中读取数据,然后关闭文件句柄
file = open("/tmp/foo.txt")
data = file.read()
file.close()
这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:
file = open("/tmp/foo.txt")
try:
data = file.read()
finally:
file.close()
虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:
with open("/tmp/foo.txt") as file:
data = file.read()
1.先执行expression,然后执行该表达式返回的对象实例的__enter__函数,然后将该函数的返回值赋给as后面的变量。(注意,是将__enter__函数的返回值赋给变量)
2.然后执行with block代码块,不论成功,错误,异常,在with block执行结束后,会执行第一步中的实例的__exit__函数

if __name__=='__main__':
    #a+可读可写覆盖
    with open("data.txt", "a+") as f:
        f.write('contour1'+'\n')
    threshold1 = 0.69
    contours1 = make_contour(template1,w1,h1,90,threshold1)
    color1 = (255, 0, 0)
    draw_contour(contours1,color1)

    img_rgb = cv2.imread("after.png")
    img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
    with open("data.txt", "a+") as f:
        f.write('\n'+'contour2'+'\n')
    color2 = (0,0,255)
    threshold2 = 0.53
    #合并轮廓
    contours2 = list(make_contour(template2, w2, h2,30,threshold2))+list(make_contour(template3, w3, h3, 30, threshold2))
    draw_contour(contours2,color2)

你可能感兴趣的:(python,python,图像识别)