2018-12-05 20:10:03 yql_617540298 阅读数 82

一、霍夫变换思想(Hough Transform)

        霍夫变换主要是利用图片所在的空间和霍夫空间之间的变换,将图片所在的直角坐标系中具有形状的曲线或直线映射到霍夫空间的一个点上形成峰值,从而将检测任意形状的问题转化成了计算峰值的问题;

        即在图片所在的直角坐标系的一个直线,转换到霍夫空间便成了一点,并且是由多条直线相交而成,我们统计的峰值也就是该相交点的橡胶线的条数。

        Hough变换的基本原理在于利用点与线的对偶性,将原始图像空间的给定曲线通过曲线表达形式变为参数空间的一个点。这样就把原始图像给定曲线的检测问题,转化为检测参数空间的峰值问题,也就是把检测整体特性转化为检测局部特性。比如直线,椭圆,圆,弧线等。

(1)设已知一黑白图像上画了一条直线,要求出这条直线所在的位置。我们知道,直线的方程可以用y=k*x+b 来表示,其中k和b是参数,分别是斜率和截距。也就是说,我们将原始图像需要检测的直线,表示成y = k*x + b, 只要找出唯一的k,b即可检测出该直线。该直线在原始图中是一系列离散点的集合,过该直线上某一点(x0,y0)的所有直线的参数都会满足方程y0=kx0+b。即点(x0,y0)确定了一条直线。而方程y0=kx0+b在参数k--b平面上是一条直线,(也可以是方程b=-x0*k+y0对应的直线).即点(x0,y0)在参数空间确定了一条直线。

(2)这样,图像x--y平面上的一个前景像素点就对应到参数平面上的一条直线。因此,图像x-y内需检测直线上的N个点,在参数平面会有N条直线。而图像x-y内的直线有唯一一个k,b,因此,相应的参数平面N条直线必然有唯一一个交点。

(3)图示:

二、倾斜文本校正

import os
import cv2
import math
import numpy as np
from scipy import misc, ndimage
from PIL import Image

filepath = 'C:/Users/Administrator/Desktop/test'
count = os.listdir(filepath)
resultpath = 'C:/Users/Administrator/Desktop/results'
 
#for filename in os.listdir(filepath):
for j in range(1,len(count)+1):
    img = cv2.imread(filepath+'/rgb_'+str(j).zfill(4)+'.png')
    img1 = Image.open(filepath+'/rgb_'+str(j).zfill(4)+'.png')
    img1 = img1.convert('RGBA')
    #img = cv2.imread(filepath+'/'+str(j).zfill(4)+'.png')
    #print("img",img)
    #img1 = Image.open(filepath+'/'+str(j).zfill(4)+'.png')
    n = img.shape[0]
    m = img.shape[1]
    #print(m,n)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray,50,150,apertureSize = 3)
    
    #霍夫变换
    lines = cv2.HoughLines(edges,1,np.pi/180,0)
    for rho,theta in lines[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)
    rotate_angle = math.degrees(math.atan(t))
    if rotate_angle > 45:
        rotate_angle = -90 + rotate_angle
    elif rotate_angle < -45:
        rotate_angle = 90 + rotate_angle
    rotate_img = ndimage.rotate(img, rotate_angle)
    misc.imsave(resultpath+'/'+'rgb_'+str(j).zfill(4)+'.png', rotate_img)

可以看到得到的结果会出现黑色色块:

region = img1.crop((5,5,10,10))
region = np.array(region)
R = np.mean(region[:,:,0])
G = np.mean(region[:,:,1])
B = np.mean(region[:,:,2])
    
card = Image.new("RGBA", (m, n), (int(R),int(G),int(B)))
card.paste(rotate_image, (0, 0, m, n), rotate_image)

2016-09-09 00:53:31 lpsl1882 阅读数 2530

  图像处理分析过程中,检测特定的形状是重要的一步。霍夫变换(Hough)通过转换坐标系,将特定形状的检测映射到参数空间中,从而根据参数空间中的值来确定特定形状的相关信息。
  Hough变换的比较简单的应用例子有检测直线和检测圆。

检测直线

  设空间中有若干点,我们要判断这些点是否能构成一条直线,即为直线检测。平面中直线的通用公式为xcos(θ)+ysin(θ)=ρ。常用的y=wx+b公式,因为不能兼容y=b的情况,所以不能使用。对于某个点,其坐标是(xi,yi),过该点的直线有无数条,这些直线统一表示为xicos(θ)+yisin(θ)=ρ,其中xi,yi是常量。反过来看,代表这些直线的公式,可以看做θ为自变量,ρ为因变量,xi,yi为常量参数的直线公式。这样,在x-y空间过(xi,yi)的无数条直线,可以在θρ空间中用一条线代表。见下图:
  这里写图片描述
  这里写图片描述
  上图是x-y空间,下图是θρ空间。其中红、绿、蓝三条线可以汇聚成一个点,说明这三条线对应的点,其在θρ空间中的直线参数是一样的。反过来就是说,穿过这三个点的无数直线中,有“三”条直线,其θ,ρ值相同,这“三“条直线是一根直线,即这三个点可以共线。
  

检测圆

  设空间有若干点,我们要判断这些点是否能构成一个圆的轮廓,即为圆检测。圆的表达式为(xx)2+(yy)2=R,参数有x,y,R。这说明,圆对应的映射空间是三维的,即xyR空间。x,y都表示空间,因此我们可以暂时将R设为常量,构建xy空间,令x’为自变量,y’为因变量,作图如下:
  这里写图片描述
  这里写图片描述
  上图是x-y空间,下图是x’-y’空间。图中绘制了一个圆和一个矩形,其中圆的轮廓并不是完全规则的。经过Hough变换后,圆上的点的变换曲线基本汇聚在一起,而矩形上的点则不能汇聚,这样就检测到圆。由于我们获取的图像并不一定是规则图形,其在参数空间中不一定能汇聚到一个点,而是在一个区域中汇聚起来,为了容许这类误差,我们可以用窗来检测参数空间中的曲线汇聚区域,而不是找曲线汇聚点,以此来检测不完全规则的特定形状。
  如果我们不知道R的值,那么我们就需要给定R取值的离散区间[R1,R2...Rn],取该区间中的值,重复做n次Hough变换检测。这样的话工作量会非常大,为了提升效率,往往会借助图像中的其他特征。
  另外,我们可以看出,由于不知道圆的尺度,我们不得不重复做多次检测。在实际的形状检测工作中,我们并不知道需要检测的复杂形状,经过了何种平移、缩放、旋转甚至是扭曲,因此需要引入不变性特征,或者针对所有可能的平移、缩放、旋转变换情况,统统做一遍检测。物体检测跟踪需要相当多的计算量。据了解,人脑为了进行视觉模式识别,至少消耗了一半的神经资源,所以人可以闭目养神,却不能捂耳朵、捏住鼻子养神:)

2017-06-22 14:51:30 qq_31531635 阅读数 1243

Opencv学习之霍夫变换
在许多应用场合中需要快速准确地检测出直线或者圆,其中一种非常有效的解决问题的方法是霍夫变换,其为图像处理中从图像中识别几何形状的基本方法之一。
霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累积结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换的结果。霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转换为统计峰值问题。

霍夫线变换–HoughLines函数、HoughLinesP函数

在使用霍夫线变换之前,首先要对图像进行边缘检测的处理,即霍夫线变换的直接输入只能是边缘二值图像。opencv支持标准霍夫变换(Standard Hough Transform,SHT)、多尺度霍夫变换(Multi-Scale Hough Transform,MSHT)和累计概率霍夫变换:是SHT的改进,在一定范围内进行霍夫变换,计算单独线段的方向以及范围,从而减少计算量,缩短计算时间。(Progressive Probabilistic Hough Transform,PPHT)三种不同的霍夫变换。
对于霍夫变换,采用极坐标系参数极径和极角(r,θ)来表示直线,每一对(r,θ)代表一条通过点(x,y)的直线,在极坐标对极径极角平面绘出所有通过它的直线,将得到一条正弦曲线,如果两个不同点进行上述操作后得到的曲线在平面θ-r相交,这就意味着它们通过同一条直线,也就是说,一条直线能够通过在平面θ-r寻找交于一点的曲线数量来检测,越多的曲线交于一点也就意味着这个交点表示的直线由更多的点组成,可以设置直线上的阈值来定义多少条曲线交于一点,这样才认为检测到了一条直线。
SHT/MSHT:void HoughLines(inputArray,outputArray,double rho,double theta,int threshold,double srn=0,double stn=0)
*第一个参数,输入图像,需为8位的单通道二进制图像。
*第二个参数,存储了霍夫线变换检测到线条的输出矢量,每一条线由具有两个元素的矢量(r, θ)表示。
*第三个参数,以像素为单位的距离精度,也就是直线搜索时的进步尺寸的单位半径。一般为1
*第四个参数,以弧度为单位的角度精度,也就是直线搜索时的进步尺寸的单位角度。一般为CV_PI/180
*第五个参数,累加平面的阈值参数,即识别某部分为途中的一条直线时它在累加平面中必须达到的值。一般为150
*第六个参数,对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离,粗略的累加器进步尺寸秩解释第三个参数rho,而精确的累加器进步尺寸为rho/srn。
*第七个参数,对于多尺度霍夫变换,stn表示第四个参数进步尺寸的单位角度theta的除数距离。

PPHT:void HoughLinesP(inputArray,outputArray,double rho,double theta,int threshold,double minLineLength=0,double maxLineGap=0)
*第一个参数,输入图像,需为8位的单通道二进制图像。
*第二个参数,存储了检测到的线条的输出矢量,每一条线由具有4个元素的矢量(x_1,y_1,x_2,y_2)表示,其中(x_1,y_1)和(x_2,y_2)是每个检测到的线段的结束点。
*第三个参数,以像素为单位的距离精度,也就是直线搜索时的进步尺寸的单位半径。一般为1
*第四个参数,以弧度为单位的角度精度,也就是直线搜索时的进步尺寸的单位角度。一般为CV_PI/180
*第五个参数,累加平面的阈值参数,即识别某部分为途中的一条直线时它在累加平面中必须达到的值。一般为150
*第六个参数,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。一般为50
*第七个参数,允许同一行点与点之间连接起来的最大距离。一般为10

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

//全局变量声明
Mat g_srcImage,g_edgeImage,g_dstImage;
vector<Vec4i>g_lines;


//主函数
int main()
{
    //载入图片
    g_srcImage=imread("/Users/new/Desktop/6.jpg");
    if(!g_srcImage.data){printf("读取源图像srcImage错误~!\n");return false;}

    namedWindow("image[origin]");
    imshow("image[origin]",g_srcImage);
    namedWindow("image[renderingsP]");
    //Canny边缘检测以及灰度颜色转换
    Canny(g_srcImage, g_edgeImage, 50, 200,3);
    cvtColor(g_edgeImage, g_dstImage, COLOR_GRAY2BGR);
    HoughLinesP(g_edgeImage, g_lines, 1, CV_PI/180, 80,50,10);
    for(size_t i;i<g_lines.size();++i)
    {
        Vec4i l=g_lines[i];
        line(g_dstImage, Point(l[0],l[1]), Point(l[2],l[3]), Scalar(23,180,55),1,CV_AA);
    }

    imshow("image[renderingsP]",g_dstImage);

    waitKey(0);
    return 0;


}


这里写图片描述

霍夫圆变换–HoughCircles函数

基本原理与霍夫线变换大体类似,只是点对应的二维极径极角空间被三维的圆心点x、y和半径r空间取代。对于圆来说,需要三个参数来表示一个圆,即(x,y,r),即圆心的位置(x,y)和半径r。在opencv中常利用“霍夫梯度法”来解决圆变换问题。
霍夫梯度法:
(1)首先对图像应用边缘检测,如Canny边缘检测。
(2)然后,对边缘图像中的每一个非零点,考虑起局部梯度,即用Sobel()函数计算x和y方向的Sobel一阶导数得到梯度。
(3)利用得到的梯度,由斜率指定的直线上的每一个点都在累加器中被累加,这里的斜率是从一个指定的最小值到指定的最大值的距离。
(4)同时,标记边缘图像中每一个非0像素的位置。
(5)然后从二维累加器中这些点中选择候选的中心,这些中心都大于给定阈值并且大于其所有近邻。这些候选的中心按照累加值降序排列,以便于最支持像素的中心首先出现。
(6)接下来对每一个中心,考虑所有的非0像素。
(7)这些像素按照其与中心的距离排序。从到最大半径的最小距离算起,选择非0像素最支持的一条路径。
(8)如果一个中心收到边缘图像非0像素最充分的支持,并且到前期被选择的中心有足够的距离,那么它就会被保留下来。
void HoughCircles(inputArray,outputArray,int method,double dp,double minDist,double param1=100,double param2=100,int minRadius=0,int maxRadiu=0)
*第一个参数,输入图像,需为8位的灰度单通道图像。
*第二个参数,存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x,y,radius)表示。
*第三个参数,使用的检测方法,目前opencv中就霍夫梯度法一种可以使用,即HOUGH_GRADIENT。
*第四个参数,用来检测圆心的累加器图像的分辨率与输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。
*第五个参数,为霍夫变换检测到的圆的圆心之间的最小距离,即让算法能明显区分的两个不同圆之间的最小距离。
*第六个参数,它是第三个参数method设置的检测方法的对应的参数,对于霍夫梯度法而言表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
*第七个参数,它是第三个参数method设置的检测方法的对应的参数,对于霍夫梯度法而言表示检测阶段圆心的累加阈值。它越小,就越可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
*第八个参数,表示圆半径的最小值。
*第九个参数,表示圆半径的最大值。
注意:使用此函数可以很容易检测出圆的圆心,但是它可能找不到合适的圆半径。可以通过第八个和第九个参数指定最小和最大的圆半径来辅助圆检测效果。或者,可以直接忽略返回半径,因为都有默认值0,然后用额外的一些步骤来进一步确定半径。

#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;

//主函数
int main()
{
    //载入源图像
    Mat srcImage=imread("/Users/new/Desktop/3.jpg");
    if(!srcImage.data){printf("读取源图像srcImage错误~!\n");return false;}
    //显示源图像
    imshow("image[origin]",srcImage);

    Mat tmpImage;
    //转换灰度图并进行图像高斯平滑
    cvtColor(srcImage, tmpImage, COLOR_BGR2GRAY);
    GaussianBlur(tmpImage, tmpImage, Size(5,5), 2,2);
    //进行霍夫圆变换
    vector<Vec3f> Circles;
    HoughCircles(tmpImage, Circles, CV_HOUGH_GRADIENT, 1.5, 15,200,110,0,0);
    //循环遍历绘制圆
    for(size_t i=0;i<Circles.size();++i)
    {
        Point center(cvRound(Circles[i][0]),cvRound(Circles[i][1]));
        int radius=cvRound(Circles[i][2]);
        //绘制圆心
        circle(srcImage, center, 3, Scalar(0,255,0),-1,8,0);
        //绘制圆轮廓
        circle(srcImage, center, radius, Scalar(155,50,255),3,8,0);
    }

    imshow("image[renderings]",srcImage);


    waitKey(0);
    return 0;
}

这里写图片描述

Opencv技巧

(1)cvRound():对double类型进行四舍五入。
(2)Scalar(55,100,195):其中数字依次代表G、B、R颜色值的数值。
(3)line():利用两点画出一条直线。

2016-06-05 11:02:22 sinat_34035510 阅读数 6818

霍夫(HOUGH)变换

        霍夫变换是图像处理中用来从图像中分离出具有某种相同特征的几何形状(通常,直线,圆等)的常用方法。经典的霍夫变换常用来检测直线,圆,椭圆等。

为什么要进行霍夫变换,当然是为了实现某种目的,比如检测,(废话)。它是利用图像全局特性而将边缘像素连接起来组成区域封闭边界的一种方法。在预先知道区域形状的条件下,利用霍夫变换可以方便地得到边界曲线而将不连续的边缘像素点连接起来。

霍夫变换的主要优点是受噪声和曲线间断的影响小。利用霍夫变换还可以直接检测某些已知形状的目标

霍夫变换的基本思想是点 —— 线的对偶性(duality),当然这只不过是所有人都这样说了,所谓线的对偶性就是线与线的某种变换之后的对应或者映射关系,实际上霍夫变换是直角坐标系空间线与变换域空间的线的映射关系,考虑傅里叶变换?当然就是说变换的目的就是便于分析。具体原理如下:

     在图像空间XY里,所有过点(x,y)的直线都满足方程:

                         y = px + q    

它也可写成:q = -px + y可以认为是参数空间PQ中过点(p’, q’)的一条直线。在图像空间中共线的点对应在参数空间里相交的线。



在图像空间中共线的点对应在参数空间里相交的线.反过来,在参数空间中相交于同一个点的所有直线在图像空间里都有共线的点与之对应。这就是点——线的对偶性。当然一般选取变换空间是时用的是极坐标空间(为什么?因为图像空间中垂直的直线p趋近于无穷!),霍夫变换根据这些关系把在图像空间中的检测问题转换到参数空间里,通过在参数空间里进行简单的累加统计完成检测任务在具体计算时,需要在参数空间PQ里建一个2-D的累加数组。设这个累加数组为A(p, q),如图所示,其中[pmin, pmax]和[qmin, qmax] 分别为预期的斜率和截距的取值范围。开始时置数组A为零,然后对每一个图像空间中的给定点,让p取遍P轴上所有可能的值,并根据式q = -px + y算出对应的q。再根据p和q的值(设都已经取整)对A累加:A(p, q)=A(p, q)+1。  累加结束后,根据A(p,q)的值就可知道有多少点是共线的,即A(p, q) 的值就是在(p, q) 处共线点的个数。同时(p, q) 值也给出了直线方程的参数,使我们得到了点所在的线。


具体实现步骤:

1)、构造一个P、Q空间的二维累加数组A(p,q)

2)、从f(x,y)的指定区域中取(xi,yi),按方程q=-pxi+yi在[pmin,pmax]中遍取可能的p值计算得到可能的q值。

3)、在对应的位置计算A(p,q) =A(p,q)+1

4)、重复2)、3)直到将从f(x,y)的指定区域中的所有点取完。此时,A(p,q)数组中最大值所对应的p,q就是方程y=px+q中的p、q值。

5)、根据y=px+q绘出f(x,y)中的直线

区域的选择:来自确认存在直线的区域。

坐标的选择:来自对存在的直线参数的估测。

霍夫变换不仅可用来检测直线和连接处在同一条直线上的点,也可以用来检测满足解析式f(x, c)=0形式的各类曲线,并把曲线上的点连接起来,这里x是一个坐标矢量,在2-D图像中是一个2-D矢量,c是一个系数矢量,它可以根据曲线的不同从2-D到3-D,4-D,…。换句话说,对写得出方程的图形都可利用霍夫变换检测

        例如圆周的检测。圆的一般方程是:

               (x - a)^2 + (y - b) ^2 = r^2

       式中有3个参数a,b, r,所以需要在参数空间里建立一个3-D的累加数组A,其元素可写为A(a, b, r) 。我们可让a和b依次变化而根据上式算出r,并对A累加:A(a, b, r) = A(a, b, r) + 1。所以其原理与检测直线上的点相同,只是复杂性增加了。

       从理论上来说,计算量和累加器尺寸随参数个数的增加是指数增加的,所以实际中霍夫变换最适合于检测较简单(即其解析表达式只含有较少参数)曲线上的点。

       设圆的半径r为已知,问题转化到2-D参数空间,如下图。原来参数的轨迹为整个圆锥部分表面,如果r已知,则参数的轨迹是半径为r的圆周。这里图像空间中的边界和参数空间里的轨迹都是圆周,所以这里是圆周——圆周对偶性。


至于代码,在MATLAB工具箱中本身集成了hough变换的函数,SO。。。。就不贴了

2018-08-25 22:04:16 qq_40962368 阅读数 5347

霍夫变换

霍夫变换(Hough Transform)是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。主要用来从图像中分离出具有某种相同特征的几何形状(如:直线、圆等)。最基本的霍夫变换是从黑白图像中检测直线。

霍夫变换是经典的检测直线的算法。其最初用来检测图像中的直线,同时也可以将其扩展,以用来检测图像中的简单结构。它最初是用于在二值化的图像中进行直线检测的。对于图像中的一条直线,利用直角坐标系,可以用公式表示为:

                                                                                   y=kx+b

如果从k-b参数空间的角度来考虑,则该直线的任意一点(x,y)将变成一个“点”。也就是说,将图像空间中所有的非零像素转换到k-b参数空间,那么它们将聚焦在一个点上,而且参数空间中的一个局部峰值点就很有可能对应着原图像空间的一条直线。不过,由于直线的斜率可能为无穷大,或者无穷小,那么在k-b参数空间就不便于对直线进行描述和刻画。所以,有人提出采用极坐标参数空间进行直线检测。在极坐标系中,直线可以表述为以下形式:

                                                                           \rho =xcos(\theta )+ysin(\theta )

 

上图(a)所示为原始的图像空间中的一个点(x_{0},y_{0}) ;(b)中所示为直角坐标系当中为过同一点的四条直线;

(c)所示为这四条直线在极坐标参数空间可以表示为四个点。

在OpenCV中,支持两种两种不同的霍夫直线变换,the Standard Hough Transform(SHT,标准霍夫变换)和Progressive Probability Hough Transform(PPHT,渐进概率式霍夫变换)。

SHT就是上述的在极坐标空间进行参数表示的方法,而PPHT是SHT的改进,它是在一定的范围内进行霍夫变换,从而减少计算量,缩短计算时间。

在OpenCV中检测直线的函数有cv2.HoughLines()-----(标准霍夫变换),cv2.HoughLinesP()------(渐进概率式霍夫变换)。

(一)标准霍夫变换

函数cv2.HoughLines()返回值实际上是一个二维数据矩阵,表述的就是上述的(\rho ,\theta),其中\rho的单位是像素长度(即直线到图像原点直线的距离,从上述图b中可以看出),\theta的单位是弧度,函数有四个参数输入:

 

通过调整边缘检测算子Canny阈值参数和标准霍夫变换阈值参数,来获取较好的检测效果。

  • 第一个参数,是需要进行检测的灰度图
  • 第二、三参数分别是\rho\theta的精确度,可以理解为步长。
  • 第四个参数为阈值T,认为当累加器中的值高于所设定的阈值T时,才认为是一条直线。
# 标准霍夫变换
img = cv2.imread('malu.jpg')
house = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 获取灰度图
edges = cv2.Canny(house, 50, 200)
lines = cv2.HoughLines(edges, 1, np.pi/180, 260)  # 霍夫变换返回的就是极坐标系中的两个参数  rho和theta
print(np.shape(lines))
lines = lines[:, 0, :]  # 将数据转换到二维
for rho, theta in lines:
    a = np.cos(theta)
    b = np.sin(theta)
    # 从图b中可以看出x0 = rho x cos(theta)
    #               y0 = rho x 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)
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 1)
cv2.imshow('img', img)
cv2.imshow('edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

(二)渐进概率式霍夫变换 

函数cv2.HoughLinesP()是一种概率直线检测,从原理上讲hough变换是一个耗时耗力的算法,尤其是对每一个点的计算,即便经过了canny转换,但有的时候点的数量依然很庞大,这时候采取一种概率挑选机制,不是所有的点都进行计算,而是随机的选取一些点来进行计算,这样的话在阈值设置上也需要降低一些。

与标准霍夫变换函数相比,在参数的输入上多了两个参数:minLineLengh(线的最短长度,比这个线段短的都忽略掉)和maxLineGap(两条直线之间的最大间隔,小于此值,就认为是一条直线)。

这个函数的输出直接是直线点的坐标位置,这样可以省去一系列for循环中的由参数空间到图像的实际坐标点的转换。

# 渐进概率式霍夫变换
img = cv2.imread('house1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 250)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 30, minLineLength=60, maxLineGap=10)
lines = lines[:, 0, :]
for x1, y1, x2, y2 in lines:
    cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 1)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

再进行边缘检测之前如果对图像进行去噪声操作,图像显示的效果将会更好。 

(三)利用霍夫变换检测圆环

圆的数学的数学表达式为:

(x-x_{0})^{2}+(y-y_{0})^{2}=r^{2}

所以一个圆的确定需要三个参数,那么就需要三层循环来实现,从而把图像上的所有点映射到三维空间上。寻找参数空间累加器的最大(或者大于某一阈值)的值。那么理论上圆的检测将比直线更耗时,然而OpenCV对其进行了优化,用了霍夫梯度法。

cv2.HoughCircles(image, method, dp, minDist, circles, param1, param2, minRadius, maxRadius)

param1和param2就是\rho\theta的精确度,最后两个参数是所要检测的圆的最大最小半径,不能盲目的检测,否则浪费时间和空间。输出就是三个参数空间矩阵。

利用霍夫检测对印章进行定位:

img = cv2.imread('yinzhang.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('img_yuantu', img)
gaussian = cv2.GaussianBlur(gray, (3, 3), 0)
circles1 = cv2.HoughCircles(gaussian, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=30, minRadius=15, maxRadius=80)
print(np.shape(circles1))             # hough_gradient 霍夫梯度法
circles = circles1[0, :, :]
circles = np.uint16(np.around(circles))
for i in circles[:]:
    cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 3)
    cv2.circle(img, (i[0], i[1]), 2, (255, 0, 255), 10)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

霍夫变换

阅读数 1546

没有更多推荐了,返回首页