opencv-python基于霍夫变换的图像矫正和表格补齐

文章目录

  • 背景`
  • 思路
  • 原始图像
  • 最终效果图
  • 一、基于霍夫变换的图像矫正
    • 1.1霍夫变换的原理
    • 2.引入库
    • 3.图像的预处理
    • 4.霍夫变换函数解释
      • (1)HoughLines
      • (2)HoughLinesP
    • 4.霍夫变换实现
    • 5.图像旋转
    • 6.效果展示
  • 本文代码总结


背景`

例如:对于一般图像,存在目标物在图像中发生位置偏移的情况,为方便图像的主观观察和使用,需要对目标物进行位置的矫正。


思路

对目标物的矫正需要获得目标物的空间位置以及对于图像的相对位置,本文采用的思路是通过霍夫变换对图像中的直线进行检测,通过限制条件获得目标直线的k值,从而通过对目标直线的矫正来达到对整个图像进行矫正的目的


提示:以下是本篇文章正文内容,下面案例可供参考

原始图像

需要矫正的图像如下所示:
opencv-python基于霍夫变换的图像矫正和表格补齐_第1张图片

最终效果图

最后要实现的效果如下,由于表格线补齐操作比较简单,这里就不再一一赘述,有需要的小伙伴可以私信我,获得相关参考代码。
opencv-python基于霍夫变换的图像矫正和表格补齐_第2张图片

一、基于霍夫变换的图像矫正

1.1霍夫变换的原理

霍夫变换原理
在这篇博客中,霍夫变换的具体思路已经讲解的非常的详细,这里就不详细介绍,下面主要讲解代码实现。

2.引入库

代码如下:

import cv2  
import math
import numpy as np

3.图像的预处理

img = cv2.imread("1.jpg")
h, w = img.shape[:2]       //这里获得图像的长和高,为了下文获得图像的中心点
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) //灰度变换,获得单通道图像,以便后文满足HoughLines的条件
edges = cv2.Canny(img, 50, 150, apertureSize=3)  //边缘检测,突出目标特征,使检测更加精准

4.霍夫变换函数解释

霍夫变换的实现方式主要有两种
(1).标准霍夫线变换(HoughLines)
(2).统计霍夫变换(HoughLinesP)
想要了解原理的小伙伴,可以参考我在上文链接的博客,这里主要讲解一下这两个函数的使用,以及各个参数的意义。

(1)HoughLines

OpenCV 提供了函数 cv2.HoughLines()用来实现霍夫直线变换,该函数要求所操作的源图像是一个二值图像,所以在进行霍夫变换之前要先将源图像进行二值化,或者进行 Canny 边缘检测。

函数 cv2.HoughLines()的语法格式为:

lines=cv2.HoughLines(image,rho,theta,threshold)

式中:

● image 是输入图像,即源图像,必须是 8 位的单通道二值图像。如果是其他类型的图像,在进行霍夫变换之前,需要将其修改为指定格式。

● rho 为以像素为单位的距离 r 的精度。一般情况下,使用的精度是 1。

● theta 为角度 θ 的精度。一般情况下,使用的精度是 π/180,表示要搜索所有可能的角度。

● threshold 是阈值。该值越小,判定出的直线就越多。通过上一节的分析可知,识别直线时,要判定有多少个点位于该直线上。在判定直线是否存在时,对直线所穿过的点的数量进行评估,如果直线所穿过的点的数量小于阈值,则认为这些点恰好(偶然)在算法上构成直线,但是在源图像中该直线并不存在;如果大于阈值,则认为直线存在。所以,如果阈值较小,就会得到较多的直线;阈值较大,就会得到较少的直线。

● 返回值 lines 中的每个元素都是一对浮点数,表示检测到的直线的参数,即(r,θ),是 numpy.ndarray 类型。

(2)HoughLinesP

概率霍夫变换对基本霍夫变换算法进行了一些修正,是霍夫变换算法的优化。它没有考虑所有的点。相反,它只需要一个足以进行线检测的随机点子集即可。

为了更好地判断直线(线段),概率霍夫变换算法还对选取直线的方法作了两点改进:

● minLineLength:检测到直线段的最短距离,如果距离小于minLineLength设定的值,将被忽略,只有线段的距离大于等于minLineLength,才视为是直线

● maxLineGap:两个线段视为在一条直线上最大间隔距离。如果两个线段目测在一条直线上,两个线段中间的空隙小于maxLineGap,会视为是一条直线,将两条线合并显示。

4.霍夫变换实现

代码实现如下:

lines = cv2.HoughLines(edges,1,np.pi/180,118)
for line in lines:
    rho, theta=line[0]
    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 x1 == x2 or y1 == y2:
        continue
    t = float(y2-y1)/(x2-x1)
    if t>20 and t<30:
        dst=t
        continue

以上代码的含义:笔者在opencv官方的函数库中也可看到类似于此标准霍夫变换的代码,这里主要是通过获得的Hough函数的返回值rho(原点到直线的垂直距离),和theta(原点到直线的垂直线段于x轴之间的夹角),对垂直线段于直线的交点,对直线的上下两端进行拓展,从而获得一定长度的直线,以及两端的点坐标

我这里需要的是介于一定角度的直线,其它的直线并不需要。(这里需要根据实际情况进行判定)


5.图像旋转

rotate_angle = math.degrees(math.atan(dst))
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center,rotate_angle, 1.0)
rotated = cv2.warpAffine(img, M, (w, h),borderValue=(255, 255, 255))

这里要注意的是,旋转角度的计算,与我们平常的坐标系不同,图像的坐标系是x=row,y=col。


6.效果展示

处理之后的图像
opencv-python基于霍夫变换的图像矫正和表格补齐_第3张图片


本文代码总结

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

img = cv2.imread("1.jpg")
h, w = img.shape[:2]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(img, 50, 150, apertureSize=3)
lines = cv2.HoughLines(edges,1,np.pi/180,118)
for line in lines:
    rho, theta=line[0]
    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 x1 == x2 or y1 == y2:
        continue
    t = float(y2-y1)/(x2-x1)
    if t<1 and t>0:
        dst=t
        continue

rotate_angle = math.degrees(math.atan(dst))
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center,angle, 1.0)
rotated = cv2.warpAffine(img, M, (w, h),borderValue=(255, 255, 255))
cv2.imshow('rotated', rotated)
cv2.waitKey(0)
cv2.destroyAllWindows()

备注:需要相关表格线补齐代码的小伙伴可以私信我

你可能感兴趣的:(计算机视觉,opencv,python,图像处理,人工智能)