首页 > 其他分享 >《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析

《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析

时间:2024-09-28 22:18:36浏览次数:8  
标签:解析 变换 透视 image cv2 OpenCV 图像 发票 轮廓

目录

一、透视变换

1、什么是透视变换

2、操作步骤

        1)选择透视变换的源图像和目标图像

        2)确定透视变换所需的关键点

        3)计算透视变换的变换矩阵

        4)对源图像进行透视变换

        5)对变换后的图像进行插值处理

二、轮廓检测

1、什么是轮廓检测

2、操作步骤

        1)图像预处理

        2)边缘检测

        3)边缘连接

        4)轮廓筛选

        5)轮廓绘制

三、项目实施

1、定义展示图片函数

2、定义自动缩放图片大小函数

3、定义轮廓点的排序函数

4、定义透视变换函数

5、读取原图并缩放

        运行结果:

6、进行轮廓检测

        运行结果:

5、绘制最大轮廓

        运行结果:

6、对最大轮廓进行透视变换

        运行结果:

7、旋转、二值化处理

        运行结果:


一、透视变换

1、什么是透视变换

        透视变换是一种图像处理技术,用于将二维平面上的图像或物体映射三维空间中。它通过改变图像的视角和投影来创建一个具有透视效果的图像。

        透视变换通常用于计算机图像形态学计算机视觉领域,用于实现图像的透视效果立体视觉图像校正等应用。它可以模拟人眼在观察远景时的透视效果,使得远处的物体看起来比近处的物体小,同时使得平行线在远处会相交的视觉效果。

        透视变换的实现通常需要通过计算图像中各点在三维空间中的坐标,并将其映射回二维平面上,从而实现透视效果。这个过程涉及到几何变换矩阵运算投影变换等数学概念和算法。

2、操作步骤

        1)选择透视变换的源图像和目标图像

                源图像是需要进行透视变换的原始图像,目标图像是希望得到的透视变换后的图像。

        2)确定透视变换所需的关键点

                根据透视变换的要求,需要选择源图像中的四个关键点以及对应的目标图像中的四个关键点。这四个关键点共同决定了透视变换的变换矩阵。

        3)计算透视变换的变换矩阵

                通过四个关键点的对应关系,使用透视变换的数学公式计算出透视变换的变换矩阵。这个变换矩阵将源图像中的像素映射到目标图像中的像素。

        4)对源图像进行透视变换

                使用计算得到的变换矩阵,对源图像中的每个像素进行变换,计算其在目标图像中的对应像素位置。

        5)对变换后的图像进行插值处理

                由于透视变换可能会导致源图像中的像素映射到目标图像中的非整数位置,因此需要对其进行插值处理,以得到最终的目标图像。

二、轮廓检测

1、什么是轮廓检测

        轮廓检测是一种图像处理技术,用于在图像中找到物体的边界。在图像处理领域中,物体的边界通常被表示为连续的曲线,这些曲线被称为轮廓。轮廓检测算法可以识别图像中的明显变化或不连续的像素,从而确定物体的形状和结构。

        轮廓检测算法的基本原理是通过分析图像中的亮度、颜色或纹理等特征,找到物体与背景之间的显著边缘或变化。常用的轮廓检测算法包括Canny边缘检测、Sobel算子、拉普拉斯算子等

        通过轮廓检测,可以实现图像分割、目标识别、形状匹配等应用。在计算机视觉和图像处理领域中,轮廓检测是一项重要的技术,广泛应用于物体检测与跟踪、图像分析与理解、机器视觉等领域。

2、操作步骤

        1)图像预处理

                首先对输入图像进行预处理,可以包括灰度化、平滑滤波、边缘增强等操作,以减少噪声和突出边缘信息。

        2)边缘检测

                使用边缘检测算法(如Canny、Sobel、拉普拉斯等)来检测图像中的边缘。这些算法通过计算像素间的梯度或差异,找到亮度或颜色变化较大的区域。

        3)边缘连接

                将离散的边缘点连接成连续的轮廓线。常用的方法包括利用边缘点的邻域信息进行连接,或者利用轮廓线的闭合性质进行曲线追踪。

        4)轮廓筛选

                根据一定的准则对检测到的轮廓进行筛选,去除无关的轮廓。可以根据轮廓的长度、面积、形状等特征进行筛选。

        5)轮廓绘制

                最后,将筛选后的轮廓绘制在原始图像上,以便观察和分析。

具体可参考博客:

《深度学习》OpenCV 图像轮廓检测、轮廓处理及代码演示icon-default.png?t=O83Ahttps://ahao1004.blog.csdn.net/article/details/141830045?fromshare=blogdetail&sharetype=blogdetail&sharerId=141830045&sharerefer=PC&sharesource=qq_64603703&sharefrom=from_link

三、项目实施

1、定义展示图片函数

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

2、定义自动缩放图片大小函数

# 调整图像高宽,保持图像宽高比不变
def resize(image,width=None,height=None ,inter=cv2.INTER_AREA):  # 输入参数为图像、可选宽度、可选高度、插值方式默认为cv2.INTER_AREA,即面积插值
    dim = None   # 存储计算后的目标尺寸w、h
    (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:  # 此处表示为width不是None,即指定了宽度,与上述方法一致,计算比值
        r = width/float(w)
        dim = (width,int(h*r))
    resized = cv2.resize(image,dim,interpolation=inter)     # 指定图像大小为上述的dim,inter默认为cV2.INTER_AREA,即面积插值,适用于缩放图像。
    return resized

3、定义轮廓点的排序函数

def order_points(pts):   # 对输入的四个点按照左上、右上、右下、左下进行排序
    rect = np.zeros((4,2),dtype='float32')   # 创建一个4*2的数组,用来存储排序之后的坐标位置
    # 按顺序找到对应坐标0123分别是左上、右上、右下、左下
    s = pts.sum(axis=1)   # 对pts矩阵的每个点的x y相加
    rect[0] = pts[np.argmin(s)]    # np.argmin(s)表示数组s中最小值的索引,表示左上的点的坐标
    rect[2] = pts[np.argmax(s)]    # 返回最大值索引,即右下角的点坐标
    diff = np.diff(pts,axis=1)   # 对pts矩阵的每一行的点求差值
    rect[1] = pts[np.argmin(diff)]   # 差值最小的点为右上角点
    rect[3] = pts[np.argmax(diff)]   # 差值最大表示左下角点
    return rect   # 返回排序好的四个点的坐标

4、定义透视变换函数

# 将透视扭曲的矩形变换成一个规则的矩阵
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

5、读取原图并缩放

# # 读取输入
image = cv2.imread('fapiao.jpg')   # 读取原图
cv_show('image',image)   # 展示原图

# 图片过大,进行缩小处理
ratio = image.shape[0] / 500.0  # 计算缩小比率,[0]表示图像的高
orig = image.copy()   # 对原图复制生成副本
image = resize(orig, height=500)   # 更改图像尺寸,输入高度自动生成宽度
cv_show('1',image)   # 展示缩放后的图片
        运行结果:

6、进行轮廓检测

gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)  # 灰度图

edged = cv2.threshold(gray,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]  # 进行二值化,cv2.THRESH_OTSU自动寻找最优全局阈值,255表示高于最优阈值时将其更改为255
cnts = cv2.findContours(edged.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[1]  # 轮廓检测
# cv2.RETR_LIST表示检索所有轮廓,但是不建立层次关系
# cv2.CHAIN_APPROX_SIMPLE 表示只保存轮廓拐点的信息
# 总体返回处理的图像、轮廓列表、层次结构,这里返回索引为1,表示返回轮廓列表

image_contours = cv2.drawContours(image.copy(),cnts,-1,(0,0,255),1)  # 绘制所有轮廓
# 在原始图像的副本上绘制了轮廓
# 绘制轮廓的位置为上述获取的拐点信息,绘制线条颜色为红色BRG(0,0,255),线条粗细为1个像素

cv_show('image_contours',image_contours)  # 展示绘制好的图片
        运行结果:

5、绘制最大轮廓

screenCnt = sorted(cnts,key = cv2.contourArea,reverse=True)[0]   # 对上述获取的轮廓列表,排序依据是轮廓面积,reverse=True表示降序,[0]表示获取面积最大的轮廓
peri = cv2.arcLength(screenCnt,True)   # 计算最大轮廓的周长
screenCnt = cv2.approxPolyDP(screenCnt,0.02*peri,True)  # 轮廓近似,近似为一个多边形,表示新的轮廓与原来的轮廓最大距离不超过原始轮廓宽度的0.02倍,True表示轮廓为闭合的
image_contour = cv2.drawContours(image.copy(),[screenCnt],-1,(0,255,0),2)  # 绘制轮廓,将上述找到的轮廓绘制到原图的副本上
cv2.imshow('image_contour',image_contour)
cv2.waitKey(0)
        运行结果:

6、对最大轮廓进行透视变换

warped = four_point_transform(orig,screenCnt.reshape(4,2)*ratio)  # 输入参数原图,将最大轮廓图形状改变为4*2的格式,即四个点,然后乘以上述定义的比率来缩放轮廓
cv2.imwrite('invoice_new.jpg',warped)   # 将经过透视变换处理的图片存入本地
cv2.namedWindow('xx',cv2.WINDOW_NORMAL)  # 设置一个窗口,名称为xx,这个窗口大小用户可通过拖动随意调节大小
cv2.imshow('xx',warped)  # 展示经过透视变换处理的图片
cv2.waitKey(0)
        运行结果:

7、旋转、二值化处理

# 二值处理
warped = cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY)   # 导入新的图片的灰度图
ref = cv2.threshold(warped,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]  # 对灰度图进行二值化处理

kernel = np.ones((2,2),np.uint8)   # 设置一个单位矩阵,大小为2*2,表示设置核kernel的大小
ref_new = cv2.morphologyEx(ref,cv2.MORPH_CLOSE,kernel)   # 闭运算,先膨胀再腐蚀
ref_new = resize(ref_new.copy(),width=500)   # 对闭运算处理完的图像重置大小
cv_show('yy',ref_new)
rotated_image = cv2.rotate(ref_new,cv2.ROTATE_90_COUNTERCLOCKWISE)  # 对图像逆时针旋转90度
cv2.imshow('result',rotated_image)
cv2.waitKey(0)
        运行结果:

标签:解析,变换,透视,image,cv2,OpenCV,图像,发票,轮廓
From: https://blog.csdn.net/qq_64603703/article/details/142622520

相关文章

  • 03_OpenCV像素操作
    importcv2img=cv2.imread('libaray.JPG',1)(b,g,r)=img[100,100]print(b,g,r)#bgr#10100---110100i=j=0forjinrange(1,500):img[i,j]=(255,255,255)foriinrange(1,500):img[i,j]=(255,255,255)#cv2.imshow('......
  • Codeforces Round 975 Div.2 C题 解析
    C题题目链接:Problem-C-Codeforces题目描述思路......
  • Windows 11 24H2新特性解析:优化安装程序与BitLocker加密管理
    Windows1124H2新特性解析:优化安装程序与BitLocker加密管理随着Windows操作系统的不断更新,微软致力于为用户提供更加流畅、安全的系统体验。在最新的Windows1124H2版本中,微软对安装程序进行了显著改进,同时引入了新的安全特性,其中BitLocker加密的变化尤为引人注目。本文......
  • Win10下如何调整鼠标滚轮行数:详细步骤与解析
    Win10下如何调整鼠标滚轮行数:详细步骤与解析鼠标滑轮,作为现代计算机操作中不可或缺的一部分,极大地提升了用户在浏览网页、文档时的效率。通过简单的滚动动作,用户可以快速浏览长页面内容,无需频繁点击滚动条或进行页面跳转。然而,不同用户对于鼠标滚轮滚动的敏感度有着不同的......
  • bs4解析并提取人民网新闻标题数据
    1.目标url:http://www.people.com.cn/2.查找标题信息所在标签:标题的文本信息在<a>标签中,且<a>标签有target属性,属性值为"_blank"。<a>标签有父辈标签<div>和<h3>。当需要根据元素的层级关系、属性组合等复杂条件定位时;文档层次分明时CSS选择器非常有用,对于熟悉CSS选择器的开发......
  • 深入汇编:计算机工作机制解析
    深入汇编:计算机工作机制解析计算机的工作原理计算机的工作原理可以概括为以下几个步骤:输入:用户通过键盘、鼠标或其他输入设备提供数据。处理:CPU(中央处理单元)根据程序指令处理数据。存储:内存和硬盘等存储设备用于保存数据和程序。输出:处理结果通过显示器、打印机等输出设备......
  • 细节解析:大模型备案安全评估要求
    ---专业解答:wacyltd唯安创远-----1.语料来源安全与《暂行办法》第七条,服务提供者应当依法开展预训练、优化训练等训练数据处理活动,使用具有合法来源的数据这一要求相对应,该《要求》在此基础上,从语料来源管理、语料搭配、可追溯性方面提出了细化要求:(1)语料来源管理方面要求使......
  • RevIN论文解析
    文章总结这篇论文提出了一种称为可逆实例归一化(RevIN)的新方法,用于解决时间序列预测中的分布变化问题。时间序列数据的统计特性(如均值和方差)随时间变化,会导致训练和测试数据分布不一致,进而影响模型的预测性能。RevIN通过先对输入数据进行归一化,再在输出层反归一化的方式,保留并......
  • Quo Vadis论文解析
    文章摘要翻译:标题: QuoVadis,UnsupervisedTimeSeriesAnomalyDetection?摘要: 文章探讨了无监督时间序列异常检测领域的现状及其未来发展方向。研究了现有方法的局限性,并提出了一些新的研究路径。作者分析了当前无监督方法的有效性,讨论了这些方法在处理多维时间序列、稀......
  • Redis 和 CDN 的应用场景区别及 Redis 大 Key 解析
    在现代互联网架构中,Redis和CDN都是非常重要的技术工具,它们在不同的应用场景中发挥着关键作用。 一、Redis的应用场景 (一)缓存场景 1. 加速数据访问:在Web应用中,Redis常被用来缓存频繁访问的数据,如数据库查询结果、页面片段等。以电商网站为例,热门商品的信息被缓......