cv2 五边形矫正,python ,多边形透视变换

news/2024/7/21 7:33:12 标签: python, 图像处理, opencv
#图像透视变换--矫正
#根据最大的5边形进行透视变换
#获取最大和最次长   周长对应的轮廓
#该轮廓进行5边形拟合逼近
#进行透视变换:应用两线交点
import numpy as np
import cv2


#大津阈值法 OSTU
def myApprox(con,pointnum=5):# con为预先得到的最大轮廓
    num = 0.001
    # 初始化时不需要太小,因为四边形所需的值并不很小
    ep = num * cv2.arcLength(con, True)
    con = cv2.approxPolyDP(con, ep, True)
    while (1):
        if len(con) == pointnum:#防止程序崩溃设置的==pointnum
            break
        else:
            num = num * 1.5
            if num >2:
                break
            ep = num * cv2.arcLength(con, True)
            con = cv2.approxPolyDP(con, ep, True)
            continue
    return con

#多边形矫正
def Polygon_correction(img):
    if len(img.shape) > 2:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    contours, hierarchy = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    perimeter_list, area_list, cnt_list, center_lsit, box_list = [], [], [], [], []
    ori_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    ori_w,ori_h = ori_img.shape[0],ori_img.shape[1]
    print('ori_w,ori_h:',ori_w,ori_h)

    #ori_img = cv2.drawContours(ori_img, contours, -1, (0, 0, 255), 2)
    cv2.imshow('binary7', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    #筛选面积最大的三个候选轮廓
    if len(contours) > 0:
        cnts = sorted(contours,
                      key=cv2.contourArea,  # 根据该函数计算的结果排序
                      reverse=True)
        cnts = cnts[:2]
        docCnt =None
        x, y, w, h = 0,0,ori_w,ori_h
        for cnt in cnts:
            #逼近法五边形拟合
            approx =myApprox(cnt, pointnum=5)
            if len(approx)==5:
                docCnt = approx
                x, y, w, h = cv2.boundingRect(docCnt) #左上角,w,h
                # 绘制矩形
                #cv2.rectangle(ori_img, (x, y + h), (x + w, y), (0, 255, 255))
                break

        #获取得到五边形边框五个原始点
        if not docCnt is None:
            points = [] #逆时针旋转排序,五个点
            for doc in docCnt:
                peak = doc[0]
                # 在角点绘制小圆圈
                #cv2.circle(ori_img, tuple(peak), 10, (0, 0, 255), 2) #橙色
                points.append(tuple(peak))

            p1, p2, p3, p4, p5 = points[0], points[1], points[2], points[3], points[4]
            #求四点确定的两条线段的交点,p1,p2,crossp,p5 作为ori转移矩阵前坐标点
            from util import get_crosss_point
            crossp = get_crosss_point(p2, p3, p4, p5)
            #如果有交点,让交点作为四个点之一,如果无交点则选择点3或则点4即可
            if crossp is not None:
                src = np.float32([p1,p2,crossp,p5])
                #外接矩阵,水平垂直矩形
                afterp1 = (x, y)
                afterp2 = (x, y + h-1)
                afterpcrossp = (x + w-1, y + h-1)
                afterp5 = (x + w-1, y)
                afterpoints = np.float32([afterp1, afterp2, afterpcrossp, afterp5])
            else:
                src = np.float32([p1,p2,p3,p5])#存在一定误差
                #根据自己需求得到多边形点
                xmin, ymin = np.array(points)[:, 0].min(), np.array(points)[:, 1].min()
                xmax, ymax = np.array(points)[:, 0].max(), np.array(points)[:, 1].max()
                sigma = (xmax - p3[0] + ymax - p4[1])/2
                sigma = int(sigma)

                afterp1 = (xmin, ymin)
                afterp2 = (xmin, ymax)
                afterp3 = (xmax - sigma, ymax)
                afterp4 = (xmax, ymax - sigma)
                afterp5 = (xmax, ymin)
                afterpoints = [afterp1, afterp2, afterp3,afterp5]

            print("原始点:", src)
            print("after点:",afterpoints)

            m = cv2.getPerspectiveTransform(src,afterpoints)
            result = cv2.warpPerspective(ori_img, m,(ori_h,ori_w))  # 透视变换

            cv2.circle(result, afterp1, 5, (0, 255, 0), 2)
            cv2.circle(result, afterp2, 5, (0, 255, 0), 2)
            cv2.circle(result, afterpcrossp, 5, (0, 255, 0), 2)
            cv2.circle(result, afterp5, 5, (0, 255, 0), 2)
            print(result.shape)
            cv2.polylines(result,[np.array(afterpoints, np.int32)], True,(255, 255, 0),1)
            cv2.imshow('result', result)
            cv2.waitKey(0)
            cv2.destroyAllWindows()
            return result
        else:
            return img
    else:
        return img



if __name__ == '__main__':
    img = cv2.imread('./data/binary7.png')#二值图
    afterPolygonimg = Polygon_correction(img)
    


 

 

 ps:求交点函数,链接为:(85条消息) python 已知四点,两条线,求交点_Lee魅儿的博客-CSDN博客


http://www.niftyadmin.cn/n/236164.html

相关文章

Linux-系统大概介绍

桌面和终端基本使用 使用CtrlAlt可以取消状态,利于TabAlt切屏 在Linux中,WIN键是Super键 打开终端,终端有点像Windows的命令行,然后Ctrlaltf2可以切换为纯命令行,Ctrlalt是调出鼠标,Ctrlaltf1切回图形用户…

项目二,easyx的加入

今天是项目的第二天 与昨天的迷离比起来今天大大的有进步 我对实现啥的功能有了一个基本的方案 1对所有路的查询那就是用dfs 2对最短路的查询就是用的floyed但是,查询是要保存路径的,所以想到了,保存每条最短路的时候 同时把最短路的前驱保存下来,我们可以通过前驱把完整的…

不得不说的创建型模式-工厂方法模式

工厂方法模式是创建型模式之一,它定义了一个用于创建对象的接口,但将具体创建的过程延迟到子类中进行。换句话说,它提供了一种通过调用工厂方法来实例化对象的方法,而不是通过直接使用 new 关键字来实例化对象。 下面是一个使用 C…

【算法】Maximum Average Subarray II 子数组最大平均数 II

文章目录644. Maximum Average Subarray II 子数组最大平均数 IIHard思考优化Tag644. Maximum Average Subarray II 子数组最大平均数 II Hard 有一个n个整数的数组nums,和一个整数k,要找出长度>k 并且 含最大平均值的连续子数组。并且输出这个最大…

任务拆解,悠然自得,自动版本的ChatGPT,AutoGPT自动人工智能AI任务实践(Python3.10)

当我们使用ChatGPT完成某些工作的时候,往往需要多轮对话,比如让ChatGPT分析、翻译、总结一篇网上的文章或者文档,再将总结的结果以文本的形式存储在本地。过程中免不了要和ChatGPT“折冲樽俎”一番,事实上,这个“交涉”…

DNS服务器的配置

要求:配置DNS服务的正反向简析 一,正向解析 1,安装bind(提供DNS服务) [rootserver ~]# yum install bind -y2,对配置文件进行修改 (1)/etc/named.conf(主配置文件&am…

Docker安装Nexus搭建Maven私服及介绍

目录前言一、Nexus是什么?二、Docker安装方式1. 拉取镜像2. 创建挂载目录3. 运行4. 容器运行日志 (可选)三、用户登录四、仓库介绍五、创建代理仓库六、上传依赖(重点)七、下载依赖常见问题1、如何把新建的仓库添加到组…

pr 是什么——可以做什么

个人简介:云计算网络运维专业人员,了解运维知识,掌握TCP/IP协议,每天分享网络运维知识与技能。座右铭:海不辞水,故能成其大;山不辞石,故能成其高。个人主页:小李会科技的…