python 图片倾斜校正

这篇具有很好参考价值的文章主要介绍了python 图片倾斜校正。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

0. 前言

进行图片校正是将拍照倾斜的图片恢复水平状态,大致思路为:

  1. 用canny算子检测出图像中的边缘轮廓线;
  2. 用霍夫线变换检测出图像中的所有直线;
  3. 筛选出接近水平方向上的直线,求出他们偏移角度的平均值;
  4. 根据倾斜角旋转矫正;
  5. 输出图片。

这里设计到几个知识点:
canny算子
原理:数字图像处理(20): 边缘检测算子(Canny算子)
cv2.Canny函数:OpenCV-Python教程(8、Canny边缘检测)
edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])

变量 内容
image 要检测的图像

threshold1 和 threshold2 的值较小时,能够捕获更多的边缘信息,下文中canny_threshold(self, img_path)函数即可可视化不同threshold的效果。

霍夫变换
原理:霍夫变换——神奇的特征提取算法
cv2.HoughLines函数:每天一练P9-Python和OpenCV做图像处理(HoughLines)

其他
Python2 math.degrees() 函数
Python scipy.ndimage.rotate用法及代码示例(该函数是按逆时针旋转)
利用向量推导坐标旋转公式(方案一)
atctan

1. 代码

在使用代码前,canny的阈值一定要根据实际情况修改!

import cv2
import math
import numpy as np
from scipy import ndimage


class HorizontalCorrection:
    def __init__(self):
        self.rotate_vector = np.array([0, 1])  # 图片中地面的法线向量
        self.rotate_theta = 0  # 旋转的角度

    def process(self, img):
        img = cv2.imread(img)  # 读取图片
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 二值化
        # cv2.imshow('gray', gray)
        # cv2.waitKey()
        edges = cv2.Canny(gray, 350, 400, apertureSize=3)  # canny算子
        cv2.imwrite('./test result/edges.png', edges)
        # cv2.imshow('edges', edges)
        # cv2.waitKey()

        # 霍夫变换
        lines = cv2.HoughLines(edges, 1, np.pi / 180, 120)
        sum = 0
        count = 0
        for i in range(len(lines)):
            for rho, theta in lines[i]:
                a = np.cos(theta)
                b = np.sin(theta)
                x0 = a * rho
                y0 = b * rho
                x1 = int(x0 + 1000 * (-b))
                y1 = int(y0 + 1000 * (a))
                x2 = int(x0 - 1000 * (-b))
                y2 = int(y0 - 1000 * (a))

                if x2 != x1:
                    t = float(y2 - y1) / (x2 - x1)
                    if t <= np.pi / 5 and t >= - np.pi / 5:
                        rotate_angle = math.degrees(math.atan(t))
                        sum += rotate_angle
                        count += 1
                        cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)

        if count == 0:
            avg_rotate_angle = 0
        else:
            avg_rotate_angle = sum / count
        self.rotate_img = ndimage.rotate(img, avg_rotate_angle)  # 逆时针旋转
        # cv2.imwrite('./test result/1.png', self.rotate_img)
        # cv2.imshow('rotate', rotate_img)
        # cv2.waitKey()

        self.rotate_theta = avg_rotate_angle  # 向量顺时针旋转公式
        self.count_rotate_vector()

    def count_rotate_vector(self):
        v1_new = (self.rotate_vector[0] * np.cos(self.rotate_theta / 180)) - \
                 (self.rotate_vector[1] * np.sin(self.rotate_theta / 180))
        v2_new = (self.rotate_vector[1] * np.cos(self.rotate_theta / 180)) + \
                 (self.rotate_vector[0] * np.sin(self.rotate_theta / 180))
        self.rotate_vector = np.array([v1_new, v2_new])

    def manual_set_rotate_vector(self, rotate_theta):
        self.rotate_theta = rotate_theta
        self.count_rotate_vector()

    def canny_threshold(self, img_path):
        img_original = cv2.imread(img_path)
        #设置窗口
        cv2.namedWindow('Canny')
        #定义回调函数
        def nothing(x):
            pass
        #创建两个滑动条,分别控制threshold1,threshold2
        cv2.createTrackbar('threshold1','Canny',50,400,nothing)
        cv2.createTrackbar('threshold2','Canny',100,400,nothing)
        while(1):
            #返回滑动条所在位置的值
            threshold1=cv2.getTrackbarPos('threshold1','Canny')
            threshold2=cv2.getTrackbarPos('threshold2','Canny')
            #Canny边缘检测
            img_edges=cv2.Canny(img_original,threshold1,threshold2)
            #显示图片
            cv2.imshow('original',img_original)
            cv2.imshow('Canny',img_edges)
            if cv2.waitKey(1)==ord('q'):
                break
        cv2.destroyAllWindows()


if __name__ == '__main__':
    horizontal_correction = HorizontalCorrection()
    # horizontal_correction.canny_threshold(r'./test image/IMG_6386.JPG')
    horizontal_correction.process(r'./test image/IMG_6386.JPG')
    print(horizontal_correction.rotate_theta)
    cv2.imwrite('./test result/1.png', horizontal_correction.rotate_img)
    cv2.imshow('rotate', horizontal_correction.rotate_img)
    cv2.waitKey()

2. 效果图

python 图片倾斜校正

python 图片倾斜校正

从图中可以看出霍夫变换根据栏杆的水平线进行校正。
彩蛋:乾元的朋友,让我看见你们的双手。

补充——用滑动条调整canny阈值

之前在一个博客看到的,但是现在找不到了,先把代码放上。

    def canny_threshold(self, img_path):
        img_original = cv2.imread(img_path)
        # 设置窗口
        cv2.namedWindow('Canny')
        # 定义回调函数
        def nothing(x):
            pass
        # 创建两个滑动条,分别控制threshold1,threshold2
        cv2.createTrackbar('threshold1', 'Canny', 50, 400, nothing)
        cv2.createTrackbar('threshold2', 'Canny', 100, 400, nothing)
        while True:
            # 返回滑动条所在位置的值
            threshold1 = cv2.getTrackbarPos('threshold1', 'Canny')
            threshold2 = cv2.getTrackbarPos('threshold2', 'Canny')
            # Canny边缘检测
            img_edges = cv2.Canny(img_original, threshold1, threshold2)
            # 显示图片
            cv2.imshow('original', img_original)
            cv2.imshow('Canny', img_edges)
            if cv2.waitKey(1) == ord('q'):
                break
        cv2.destroyAllWindows()

其他

cv2.HoughLines返回值的处理方式进行了修改。文章来源地址https://www.toymoban.com/news/detail-443992.html

import cv2
import math
import numpy as np
from scipy import ndimage


class HorizontalCorrection:
    def __init__(self):
        self.rotate_vector = np.array([0, 1])  # 图片中地面的法线向量
        self.rotate_theta = 0  # 旋转的角度

    def process(self, img):
        img = cv2.imread(img)  # 读取图片
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 二值化
        # cv2.imshow('gray', gray)
        # cv2.waitKey()
        edges = cv2.Canny(gray, 350, 400, apertureSize=3)  # canny算子
        cv2.imwrite('./test result/edges.png', edges)
        # cv2.imshow('edges', edges)
        # cv2.waitKey()

        # 霍夫变换
        lines = cv2.HoughLines(edges, 1, np.pi / 180, 120)
        sum = 0
        count = 0
        for r_theta in lines:
            arr = np.array(r_theta[0], dtype=np.float64)
            rho, theta = arr
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a * rho
            y0 = b * rho
            x1 = int(x0 + 1000 * (-b))
            y1 = int(y0 + 1000 * (a))
            x2 = int(x0 - 1000 * (-b))
            y2 = int(y0 - 1000 * (a))

            if x2 != x1:
                t = float(y2 - y1) / (x2 - x1)
                if t <= np.pi / 5 and t >= - np.pi / 5:
                    rotate_angle = math.degrees(math.atan(t))
                    sum += rotate_angle
                    count += 1
                    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)

        if count == 0:
            avg_rotate_angle = 0
        else:
            avg_rotate_angle = sum / count
        self.rotate_img = ndimage.rotate(img, avg_rotate_angle)  # 逆时针旋转
        # cv2.imwrite('./test result/1.png', self.rotate_img)
        # cv2.imshow('rotate', rotate_img)
        # cv2.waitKey()

        self.rotate_theta = avg_rotate_angle  # 向量顺时针旋转公式
        self.count_rotate_vector()

    def count_rotate_vector(self):
        v1_new = (self.rotate_vector[0] * np.cos(self.rotate_theta / 180)) - \
                 (self.rotate_vector[1] * np.sin(self.rotate_theta / 180))
        v2_new = (self.rotate_vector[1] * np.cos(self.rotate_theta / 180)) + \
                 (self.rotate_vector[0] * np.sin(self.rotate_theta / 180))
        self.rotate_vector = np.array([v1_new, v2_new])

    def manual_set_rotate_vector(self, rotate_theta):
        self.rotate_theta = rotate_theta
        self.count_rotate_vector()

    def canny_threshold(self, img_path):
        img_original = cv2.imread(img_path)
        #设置窗口
        cv2.namedWindow('Canny')
        #定义回调函数
        def nothing(x):
            pass
        #创建两个滑动条,分别控制threshold1,threshold2
        cv2.createTrackbar('threshold1','Canny',50,400,nothing)
        cv2.createTrackbar('threshold2','Canny',100,400,nothing)
        while(1):
            #返回滑动条所在位置的值
            threshold1=cv2.getTrackbarPos('threshold1','Canny')
            threshold2=cv2.getTrackbarPos('threshold2','Canny')
            #Canny边缘检测
            img_edges=cv2.Canny(img_original,threshold1,threshold2)
            #显示图片
            cv2.imshow('original',img_original)
            cv2.imshow('Canny',img_edges)
            if cv2.waitKey(1)==ord('q'):
                break
        cv2.destroyAllWindows()


if __name__ == '__main__':
    horizontal_correction = HorizontalCorrection()
    # horizontal_correction.canny_threshold(r'./test image/IMG_6386.JPG')
    horizontal_correction.process(r'./test image/IMG_6386.JPG')
    print(horizontal_correction.rotate_theta)
    cv2.imwrite('./test result/1.png', horizontal_correction.rotate_img)
    cv2.imshow('rotate', horizontal_correction.rotate_img)
    cv2.waitKey()

到了这里,关于python 图片倾斜校正的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MATLAB图像倾斜校正算法实现:图像倾斜角检测及校正

    在本文中,随着多媒体技术的不断发展,数码相机,高清拍照手机等多媒体设备己经在人们的生活中占据了越来越重要的地位 ( 点击文末“阅读原文”获取完整 代码数据 ) 。 通过采用图像处理技术,可以将数码设备采 集到的文字、图片等信息转化成其他信息形势输出,例

    2024年02月04日
    浏览(69)
  • 基于深度学习的指针式仪表倾斜校正方法——论文解读

    中文论文题目:基于深度学习的指针式仪表倾斜校正方法 英文论文题目:Tilt Correction Method of Pointer Meter Based on Deep Learning 周登科、杨颖、朱杰、王库.基于深度学习的指针式仪表倾斜校正方法[J].计算机辅助设计与图形学学报, 2020, 32(12):9.DOI:10.3724/SP.J.1089.2020.18288.        针对仪

    2024年02月12日
    浏览(34)
  • 计算机视觉——基于傅里叶幅度谱文档倾斜度检测与校正

    在计算机视觉领域,处理文档数据时,OCR算法的性能往往会受到文档的倾斜度影响。如果文档在输入到模型之前没有经过恰当的校正,模型就无法期待模型能够提供准确的预测结果,或者模型预测的精度会降低。例如,在信息提取系统中,如果向OCR模型提供了倾斜的图像,模

    2024年04月10日
    浏览(30)
  • opencv进行双目标定以及极线校正 python代码

    参考博客 OpenCV相机标定全过程 [OpenCV实战]38 基于OpenCV的相机标定 opencv立体标定函数 stereoCalibrate() 将打印的结果保存到标定文件中即可 参考博客 机器视觉学习笔记(8)——基于OpenCV的Bouguet立体校正 小白视角之Bouguet双目立体校正原理 校正前 左图 右图 校正后

    2024年02月11日
    浏览(27)
  • 使用Python进行立体几何和立体校正的综合教程

    需要多个视图 在相机的针孔模型中,光线从物体上反射出来,照射到胶片上形成图像。因此,沿着同一条光线的所有点都将对应于图像中的一个点。 因此,给定图像中的一个点,不可能确定其在世界上的准确位置,也就是说,我们无法从单个图像中恢复深度。 我们也无法从

    2024年02月09日
    浏览(26)
  • OpenCV图片校正

    遇到偏的图片想要校正成水平或者垂直的。 对于倾斜的图片通过矫正可以得到水平的图片。一般有如下几种基于opencv的组合方式进行图片矫正。 1、傅里叶变换 + 霍夫变换+ 直线 + 角度 + 旋转 2、边缘检测 + 霍夫变换 + 直线+角度 + 旋转 3、四点透视 + 角度 + 旋转 4、检测矩形轮

    2024年02月12日
    浏览(30)
  • opencv对相机进行畸变校正,及校正前后的坐标对应

    目前有个项目,需要用到热成像相机。但是这个热成像相机它的畸变比较厉害,因此需要用标定板进行标定,从而消除镜头畸变。 同时需要实现用户用鼠标点击校正后的画面后,显示用户点击位置的像素所代表的温度。 另外热成像sdk中还有个功能:选定一个rect,可以返回这

    2024年02月14日
    浏览(33)
  • mysql数据库自动生成默认时间不正确进行校正

    引言 查看数据库数据,发现表中自动生成的创建时间不正确,故先使用 SELECT CURRENT_TIMESTAMP; sql验证自动生成的时间是否是不正确的。经验证确定是自动生成的时间不正确,进而想到了对时间进行校正。 校正过程 首先查看数据库时间的时区是否是当地的。 SELECT @@global.time_zo

    2024年02月20日
    浏览(36)
  • 使用python对图片进行压缩

    对于图片,强行被定义高和宽会变形,我们希望图片被改变大小后,比例保持不变,完成对图片的压缩。 1.pillow : pip install pillow -i https://pypi.douban.com/simple 2. os : 连接文件,并获取文件夹下的文件名 获取picture文件下的相关图片的路径,将路径放到列表里面进行存储 使用Image模

    2024年02月13日
    浏览(40)
  • Python 对图片进行颜色识别

    场景:在进行压力测试时,需要判断图片的某一块区域是否是黑色 这里使用的是OpenCV库对图片进行颜色的识别,几乎可以识别所有常见的颜色 直接上代码 运行结果如下:   颜色可以判断出来了,可以做的事情就方便很多了 比如在尽行压力测试时,去判断截图区域是否是黑

    2024年02月11日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包