计算机视觉--opencv---如何识别不同方向图片的识别
数据准备:
jt.jpg
jiant.jpg
一、使用 OpenCV 实现多模板匹配
步骤和原理:
- 读取图像和模板:首先需要加载待检测的原始图像和作为模板的图像
- 选择匹配方法:OpenCV 提供了多种匹配算法(如 TM_CCOEFF、TM_CCOEFF_NORMED 等)
- 执行模板匹配:使用
cv2.matchTemplate()
函数进行匹配计算 - 设置阈值筛选结果:通过设定合适的阈值,找出所有匹配度高于阈值的区域
- 处理重叠区域:如果匹配结果有重叠,通常保留匹配度最高的区域
示例代码
import cv2
import numpy as npimg_rgb = cv2.imread('jiant.jpg')
img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
template = cv2.imread('jt.jpg',0)
h,w = template.shape[:2]res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)threshold = 0.9loc = np.where(res>=threshold)for pt in zip(*loc[::-1]):cv2.rectangle(img_rgb,pt,(pt[0]+w,pt[1]+h),(0,0,255),1)cv2.imshow('1',img_rgb)
cv2.waitKey(0)
二、opencv图像旋转
这里介绍的是固定角度旋转,非特定角度需要详解数学原理,后面再介绍
固定角度旋转的技术特性
固定角度旋转(90°、180°、270°)与任意角度旋转相比,具有独特的技术优势:
- 像素位置可预测:旋转后每个像素的新位置是整数坐标,无需复杂的插值计算(仅在边缘处理时可能用到简单插值)
- 画布尺寸确定性变化:旋转后图像的宽高比会按规律变化(90° 和 270° 旋转时宽高互换,180° 旋转时尺寸不变)
- 计算效率极高:底层采用矩阵转置等优化算法,避免了三角函数运算,速度比任意角度旋转快 10 倍以上
- 无信息丢失:完整保留原始图像的所有像素信息,不会因旋转角度导致内容裁剪(除非主动设置)
cv2.rotate () 函数深度解析
函数原型与参数说明
rotated_img = cv2.rotate(src, rotateCode)
src:输入图像,必须是 numpy 数组格式(
ndarray
),可以是单通道(灰度图)、三通道(彩色图)或四通道(带 alpha 通道的图像)rotateCode:旋转模式参数,决定旋转方向和角度,仅支持以下三个预定义值:
cv2.ROTATE_90_CLOCKWISE
:顺时针旋转 90°cv2.ROTATE_180
:顺时针旋转 180°(与逆时针旋转 180° 结果相同)cv2.ROTATE_90_COUNTERCLOCKWISE
:逆时针旋转 90°(等价于顺时针旋转 270°)
返回值:旋转后的图像,与输入图像具有相同的数据类型和通道数
旋转模式的底层实现机制
顺时针旋转 90°(ROTATE_90_CLOCKWISE)
- 实现原理:先对图像进行转置(transpose),再进行水平翻转(flip)
- 尺寸变化:原图像 (w, h) → 旋转后 (h, w)
- 数学表达:新坐标 (x', y') 与原坐标 (x, y) 的关系为 x' = y,y' = w-1-x
180° 旋转(ROTATE_180)
- 实现原理:对图像进行两次水平翻转(或两次垂直翻转),或直接反转像素顺序
- 尺寸变化:原图像 (w, h) → 旋转后 (w, h)(尺寸不变)
- 数学表达:新坐标 (x', y') 与原坐标 (x, y) 的关系为 x' = w-1-x,y' = h-1-y
逆时针旋转 90°(ROTATE_90_COUNTERCLOCKWISE)
- 实现原理:先对图像进行转置(transpose),再进行垂直翻转(flip)
- 尺寸变化:原图像 (w, h) → 旋转后 (h, w)
- 数学表达:新坐标 (x', y') 与原坐标 (x, y) 的关系为 x' = h-1-y,y' = x
示例代码:
import cv2
import numpy as np
# 方法一
img = cv2.imread('./jt.jpg')
# 旋转 90 度, k=-1 表示顺时针旋转 90 度
rotated_image1 = np.rot90(img, k=-1)
# 旋转 90 度, k=1 表示逆时针旋转 90 度
rotated_image2 = np.rot90(img, k=1)cv2.imshow(winname='yuantu', mat=img)
cv2.imshow(winname='rotated_image1', mat=rotated_image1)
cv2.imshow(winname='rotated_image2', mat=rotated_image2)
cv2.waitKey(0)
cv2.destroyAllWindows()# 方法二
rotated_image = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE) # 顺时针90度
rotated_image1 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE) # 逆时针90度
rotated_image2 = cv2.rotate(img, cv2.ROTATE_180) # 旋转180度
cv2.imshow(winname='shun90', mat=rotated_image)
cv2.imshow(winname='ni90', mat=rotated_image1)
cv2.imshow(winname='180', mat=rotated_image2)
cv2.waitKey(0)
三、实现图片中多角度识别的案例
需要实现在大图片中识别不同角度的小图片
读取图像文件
img_rgb = cv2.imread('jiant.jpg') # 读取原始彩色图像 img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY) # 转换为灰度图 template = cv2.imread('jt.jpg',0) # 读取模板图像,0表示以灰度模式读取
生成旋转后的模板
image1 = np.rot90(template, k=-1) # 将模板逆时针旋转90度 image2 = np.rot90(template, k=1) # 将模板顺时针旋转90度
定义匹配函数
ping
def ping(template,img_rgb):h, w = template.shape[:2] # 获取模板的高度和宽度# 使用归一化相关系数方法进行模板匹配res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)threshold = 0.9 # 匹配阈值,只保留匹配度大于等于0.9的结果loc = np.where(res >= threshold) # 找到所有匹配度超过阈值的位置# 遍历所有匹配位置,绘制矩形标记for pt in zip(*loc[::-1]):cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1)
执行匹配并显示结果
ping(template,img_rgb) # 用原始模板匹配 ping(image1,img_rgb) # 用逆时针旋转90度的模板匹配 ping(image2,img_rgb) # 用顺时针旋转90度的模板匹配cv2.imshow('1',img_rgb) # 显示标记后的图像 cv2.waitKey(0) # 等待用户按键,保持窗口显示
完整代码
import cv2
import numpy as npimg_rgb = cv2.imread('jiant.jpg')
img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
template = cv2.imread('jt.jpg',0)image1 = np.rot90(template, k=-1)
image2 = np.rot90(template, k=1)def ping(template,img_rgb):h, w = template.shape[:2]res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)threshold = 0.9loc = np.where(res >= threshold)for pt in zip(*loc[::-1]):cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1)ping(template,img_rgb)
ping(image1,img_rgb)
ping(image2,img_rgb)
cv2.imshow('1',img_rgb)
cv2.waitKey(0)
结果: