python批量实现模板匹配处理,并将图片进行标记和裁剪保存

  • Post author:
  • Post category:python




简介



主要是通过python的opencv进行模板匹配识别到想要得到的物体;



然后通过opencv进行裁切图片,得到最终需要的图片




核心内容


①模板匹配,带有nms的模板匹配


②批量处理图片,并保存




代码


import os
import cv2
import time
import numpy as np



def py_nms(dets, thresh):
    """Pure Python NMS baseline."""
    # x1、y1、x2、y2、以及score赋值
    # (x1、y1)(x2、y2)为box的左上和右下角标
    x1 = dets[:, 0]
    y1 = dets[:, 1]#左上角的坐标值

    x2 = dets[:, 2]
    y2 = dets[:, 3]#右下角的阈值

    scores = dets[:, 4]
    # 每一个候选框的面积
    areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    # order是按照score降序排序的,从大到小
    order = scores.argsort()[::-1]
    # print("order:",order)

    keep = []
    while order.size > 0:
        i = order[0]
        keep.append(i)
        # 计算当前概率最大矩形框与其他矩形框的相交框的坐标,会用到numpy的broadcast机制,得到的是向量
        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])
        # 计算相交框的面积,注意矩形框不相交时w或h算出来会是负数,用0代替
        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        # 计算重叠度IOU:重叠面积/(面积1+面积2-重叠面积)
        ovr = inter / (areas[i] + areas[order[1:]] - inter)
        # 找到重叠度不高于阈值的矩形框索引
        inds = np.where(ovr <= thresh)[0]
        # print("inds:",inds)
        # 将order序列更新,由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1,所以要把这个1加回来
        order = order[inds + 1]
    return keep


def template(img_gray, template_img, template_threshold):
    '''
    img_gray:待检测的灰度图片格式
    template_img:模板小图,也是灰度化了
    template_threshold:模板匹配的置信度
    '''

    h, w = template_img.shape[:2]#获取模板的高和宽
    res = cv2.matchTemplate(img_gray, template_img, cv2.TM_CCOEFF_NORMED)#模板匹配的方式
    start_time = time.time()
    loc = np.where(res >= template_threshold)  # 大于模板阈值的目标坐标,返回的就是矩阵的行列索引值,其中行坐标为坐标的y值,列坐标为x值
    score = res[res >= template_threshold]# 大于模板阈值的目标置信度cv2.matchTemplate(img_gray, template_img, cv2.TM_CCOEFF_NORMED)[res >= template_threshold]完整写法
    # 将模板数据坐标进行处理成左上角、右下角的格式
    xmin = np.array(loc[1])#列坐标为x值
    ymin = np.array(loc[0])#横坐标为y值
    xmax = xmin + w
    ymax = ymin + h

    xmin = xmin.reshape(-1, 1)  # 变成n行1列维度
    xmax = xmax.reshape(-1, 1)  # 变成n行1列维度
    ymax = ymax.reshape(-1, 1)  # 变成n行1列维度
    ymin = ymin.reshape(-1, 1)  # 变成n行1列维度
    score = score.reshape(-1, 1)  # 变成n行1列维度

    data_hlist = []
    data_hlist.append(xmin)
    data_hlist.append(ymin)
    data_hlist.append(xmax)
    data_hlist.append(ymax)
    data_hlist.append(score)
    data_hstack = np.hstack(data_hlist)  # 将xmin、ymin、xmax、yamx、scores按照列进行拼接       np.hstack():在水平方向上平铺  np.vstack():在竖直方向上堆叠
    thresh = 0.3  # NMS里面的IOU交互比阈值

    keep_dets = py_nms(data_hstack, thresh)
    print("nms time:", time.time() - start_time)
    dets = data_hstack[keep_dets]  
    return dets

def saveresult(name,file,img_rgb):
    isExists = os.path.exists("./"+ str(name)+'/')
    if not isExists:  # 判断如果文件不存在,则创建
        os.makedirs("./"+ str(name)+'/')
        print("./"+ str(name)+'/'+"目录创建成功")

    out =str(file.split('.')[0])
    filename="./"+ name+'/%s.jpg'%(out)
    print('已匹配图片:'+filename)
    cv2.imwrite(filename, img_rgb)

def savecut(name,file,cut):
    isExists = os.path.exists("./"+ str(name)+'/')
    if not isExists:  # 判断如果文件不存在,则创建
        os.makedirs("./"+ str(name)+'/')
        print("./"+ str(name)+'/'+"目录创建成功")

    out =str(file.split('.')[0])
    filename="./"+ name+'/%s.jpg'%(out)
    print('已裁切图片:'+filename)
    cv2.imwrite(filename, cut)




if __name__ == "__main__":
    jpg_path = "./images/"  # 图片存放文件夹的路径
    file_walk = os.listdir(jpg_path)

    for file in file_walk:
        file1 = os.path.join(jpg_path, file)
        img_rgb = cv2.imread(file1)
        img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
        template_img = cv2.imread('1.jpg', 0)  # 模板
        template_threshold = 0.45 # 模板置信度
        dets = template(img_gray, template_img, template_threshold)
        for coord in dets:
            cv2.rectangle(img_rgb, (int(coord[0]), int(coord[1])), (int(coord[2]), int(coord[3])), (0, 0, 255), 2)
            cut = img_rgb[int(coord[1]):int(coord[3]),int(coord[0]):int(coord[2])]#裁切坐标为(y0:y1,x0:x1)

        save1 = saveresult('save',file,img_rgb)
        save2 = savecut('savepicture',file,cut)



    print("*******************************************************************************")
    print('*                            已完成模板匹配任务                                *')
    print("*******************************************************************************")






参考、致谢



非常感谢下列博主写出的优秀好文



http://t.csdn.cn/UQBZr


http://t.csdn.cn/o7Ln8


http://t.csdn.cn/oVJgm


http://t.csdn.cn/9cJb4



希望本人写的代码能给大家带来一丝便利,谢谢大家支持




版权声明:本文为m0_61348166原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。