图像投影(透视)转化技术和特征提取

发布于:2025-09-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

目录

一.图像透视变换技术

1.图像透视变换技术介绍

2.处理流程与代码实现

①预处理

②轮廓获取和筛选

③角点定位,检测并找到输入图像四个顶点的坐标

④排序这些顶点获取正确的空间顺序

⑤计算目标变换后的矩形区域尺寸

⑥调用方法得到变换后的矩阵

二.图像特征提取

1.Harris角点检测

2.SIFT特征提取(重点)


一.图像透视变换技术

1.图像透视变换技术介绍

  • 背景与目标:介绍一种图像处理技术,用于将倾斜、扭曲的发票等图片(如票据上的发票图像),通过透视变换,矫正为标准的矩形(如正方形),使文字更清晰易读
  • 核心方法:利用OpenCV中的函数,核心步骤包括:
    • 使用findContours和轮廓近似(approxPolyDP)定位并获取被处理物体(如发票)的四个角点坐标,这两个点集分别为“变化前”与“变化后的目标点”。
    • 应用getPerspectiveTransform函数计算出描述两者之间变换关系的“变换矩阵M”。
    • 利用透视变换函数(warpPerspective),应用变换矩阵M处理原图,生成矫正后的标准矩形图。

2.处理流程与代码实现

①预处理

import cv2
import numpy as np
def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)

def resize(image,width=None,height=None,inter=cv2.INTER_AREA):
    dim=None
    (h,w)=image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r=height/float(h)
        dim=(int(w*r),height)
    else:
        r=width/float(w)
        dim=(width,int(h*r))
    resized=cv2.resize(image,dim,interpolation=inter)#默认为cv2.INTER_AREA,即面积插值适用于缩放图像
    return resized

首先读取原图,由于真实发票尺寸过大,会先进行缩放,以方便后续处理,并计算出缩放比例方便后续使用。

image=cv2.imread('fapiao.jpg')
#图片过大,进行缩小处理
ratio=image.shape[0]/500.0#计算缩小比例
orig=image.copy()
image=resize(orig,height=500)
cv_show('img',image)

②轮廓获取和筛选

  • 将图片转为灰度图并进行二值化处理。
print('Step1 轮廓检测')
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

edged=cv2.threshold(gray,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
  • 使用findContours获取所有轮廓
cnts=cv2.findContours(edged,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[-2]
image_contours=cv2.drawContours(image.copy(),cnts,-1,(0,0,255),2)
cv_show('image_contours',image_contours)

  • 再通过counterArea对轮廓按面积降序排列,并选取最大的轮廓(即最外层的发票轮廓)。
print('Step2 找到最大轮廓')
screenCnt=sorted(cnts,key=cv2.contourArea,reverse=True)[0]

③角点定位,检测并找到输入图像四个顶点的坐标

  • 使用对轮廓进行近似处理(approxPolyDP),将其约简为四个顶点坐标。
peri=cv2.arcLength(screenCnt,True)
screenCnt=cv2.approxPolyDP(screenCnt,0.05*peri,True)#轮廓近似
print(screenCnt.shape)

#(4, 1, 2)
image_contours=cv2.drawContours(image.copy(),[screenCnt],-1,(0,0,255),2)
cv_show('image_contours',image_contours)

④排序这些顶点获取正确的空间顺序

  • 排序原理:通过数学运算分析点的相对位置进行排序。
    • 计算每个点的横坐标 (x) 与纵坐标 (y) 之和 (x+y),以此区分左右上下附近的位置:
      • 和最大的点为右下角。
      • 和最小的点为左上角。
    • 计算每个点的纵坐标 (y) 与横坐标 (x) 的差值 (y-x),以此区分左右上下的精确位置:
      • 差值最小的点为右上角。
      • 差值最大的点为左下角。
  • 实现方式:将某个坐标的 x+y 和 y-x 进行排序,得到各点坐标的索引,然后将四个坐标准确地按“左上、右下、左下”等顺序存入返回的新数组中。

这里我们直接定义一个方法实现

def order_points(pts):
    rect=np.zeros((4,2),dtype='float32')
    #按顺序找到对应坐标0123即左上右上右下左下
    s=pts.sum(axis=1)#每行求和
    rect[0]=pts[np.argmin(s)]
    rect[2]=pts[np.argmax(s)]
    diff=np.diff(pts,axis=1)#每行求差
    rect[1]=pts[np.argmin(diff)]
    rect[3]=pts[np.argmax(diff)]
    return rect

⑤计算目标变换后的矩形区域尺寸

  • 计算尺寸:根据已排序的四个角点坐标,利用勾股定理计算出原始图形的长边和宽边,分别定义为W和H,以确定变换后的标准尺寸。
  • 构建矩阵:调用getperspective transform函数,传入变换前后的四个角点坐标,即可获得代表变换规则的3x3变换矩阵M。
  • 应用变换:通过warpPerspective函数,对原始图像应用该变换矩阵M,并将输出尺寸设为计算出的(W,H),从而得到最后的正向透视图。

我们直接调用上面定义的方法得到已排序的四个角点坐标然后再计算目标变换后的矩形区域尺寸

def four_point_transform(image,pts):
    #获取输入坐标点
    rect=order_points(pts)
    (tl,tr,br,bl)=rect
    #计算输入的w和h值
    widthA=np.sqrt(((br[0]-bl[0])**2+(br[1]-bl[1])**2))
    widthB=np.sqrt(((tr[0]-tl[0])**2+(tr[1]-tl[1])**2))
    maxWidth=max(int(widthA),int(widthB))
    heightA=np.sqrt(((tr[0]-br[0])**2)+(tr[1]-br[1])**2)
    heightB=np.sqrt(((tl[0]-bl[0])**2)+(tl[1]-bl[1])**2)
    maxHeight=max(int(heightA),int(heightB))
    #变换对应的坐标位置
    dst=np.array([[0,0],[maxWidth-1,0],[maxWidth-1,maxHeight-1],[0,maxHeight-1]],dtype='float32')
    M=cv2.getPerspectiveTransform(rect,dst)#M是获取到的转换之间的关系
    warped=cv2.warpPerspective(image,M,(maxWidth,maxHeight))
    #返回变换后结果
    return warped

⑥调用方法得到变换后的矩阵

warped=four_point_transform(orig,screenCnt.reshape(4,2)*ratio)

逆时针旋转90°后保存并展示

warped=np.rot90(warped,1)
cv2.imwrite('invoice_new.jpg',warped)
cv2.namedWindow('xx',cv2.WINDOW_NORMAL)
cv_show('xx',warped)

后面就是做一个简单的图像形态学处理使字体更清晰

gray=cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY)
warped=cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
warped=resize(warped,width=400)
cv_show('warped',warped)
erosion=cv2.erode(warped,(2,2),iterations=1)
cv_show('erosion',erosion)

二.图像特征提取

1.Harris角点检测

Harris角点检测算法是一种常用的计算机视觉算法,用于检测图像中的角点。该算法通过计算图像中每个像素的局部自相关矩阵,来判断该像素是否为角点。

  • 功能: 用于检测图像中像素点与周围环境的差异度大的位置,即“角点”。
  • 原理: 通过计算包含像素的局部区域在不同方向滑动时的灰度变化来判断如果在任意方向上变化都较大,则认为是角点。
  • 实现: 使用OpenCV的cv2.cornerHarris()函数。需要设置如block_size、ksize和k等参数。
  • 结果: 返回一个Dst矩阵,其值越大越可能为角点。通过设定一个阈值(如Dst值大于Dst_max * 0.01)来筛选最终的角点位置。
import cv2
import numpy as np

#角点检测
img=cv2.imread('img.png')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst=cv2.cornerHarris(gray,4,3,0.04)
#设置阈值标记检测到的角点
img[dst>0.05*dst.max()]=[0,0,255]
cv2.imshow('img',img)
cv2.waitKey(0)

2.SIFT特征提取(重点)

SIFT(Scale Invariant Feature Transform)尺度不变特征变换。SIFT特征具有对旋转、尺度缩放、亮度变化等保持不变性,是一种非常稳定的局部特征

  • 功能: 用于稳定、高效地提取图像的局部特征,对旋转、尺度缩放、亮度变化等具有很强的鲁棒性。
  • 原理: 通过对输入图像进行多尺度的高斯差分(DoG)处理,结合关键点的定位和描述,形成一组对图像变化不敏感的特征。
  • 特点:1、图像的局部特征,对旋转、尺度缩放、亮度变化保持不变,对视角变化、仿射变换、噪声也保持一定程度的稳定性。 2、独特性好,信息量丰富,适用于海量特征库进行快速、准确的匹配。 3、多量性,即使是很少几个物体也可以产生大量的SIFT特征 4、高速性,经优化的SIFT匹配算法甚至可以达到实时性 5、扩招性,可以很方便的与其他的特征向量进行联合。
  • 核心输出: 对图像中的每个检测到的关键点,都会生成一个128维的向量(描述符),用以精确描述该点周围的纹理、形状和梯度等特征。一个完整的特征描述包含了关键点本身的位置和来自每个关键点的描述符。
  • 应用价值: 大量的商业应用(如指纹识别、人脸识别)均依赖于SIFT等算法提取、比较和匹配这些特征。
'''-----特征提取sift(重点)----'''
#检测图像中的关键点
img=cv2.imread('img.png')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sift=cv2.SIFT_create()
kp=sift.detect(gray)
img_sift=cv2.drawKeypoints(img,kp,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('img——sift',img_sift)
cv2.waitKey(0)

#计算关键点描述符des
kp,des=sift.compute(img,kp)
print(np.array(kp).shape,des.shape)

关键点描述符des也是非常重要,用于后续的特征匹配


网站公告

今日签到

点亮在社区的每一天
去签到