qt图像算法—图像的Hough直线检测之c++实现(不调包)

【源码下载】GitCode,关键词【qt图像算法】

整套项目源码内容包含

[1].根据算法原理,编写纯c++源码,不调用外源库opencv 等;
[2].包括各种图像处理的基本算法,包含腐蚀膨胀,缩放,转置,镜像,平移,均衡变化,灰度拉升,灰度阈值,灰度非线性,转灰度,灰度线性,旋转,简单平滑,高斯平滑,轮廓跟踪,种子算法,hough直线检测,拉普拉斯,带方向边缘检测,常规边缘检测(梯度算子、Roberts算子和Sobel算子),中值滤波,反色操作等;
[3].程序中有完整的注释,便于大家很好理解代码。

1.基本原理

在平面直角坐标系中,直线可以用y=k*x + b表示,在下图中,如果假设以O为原点,x轴为极坐标轴,并且OA与极坐标轴的夹角为798a135f47a1ec3dc636082b66dc9938.gif,那么点A可由极坐标957a2430659f4e483a1f09d7c1293139.png表示,经过一系列公式转换可得bd8ef8db665ef902b9472377fc8a60af.gif,任意一组957a2430659f4e483a1f09d7c1293139.png可以确定一条直线,检测直线主要是以下几步:

1)建立一个二维数组houghbuf[360][p],其中p的长度为图像对角线长度(对应着d829ea9eb4684ef640b7d92a191ad66c.gif),其中360°(对应着798a135f47a1ec3dc636082b66dc9938.gif

2)循环遍历图像的坐标(x,y)的时候,798a135f47a1ec3dc636082b66dc9938.gif也同时由0-360取值遍历,并代入公式bd8ef8db665ef902b9472377fc8a60af.gif,根据957a2430659f4e483a1f09d7c1293139.png来累加(1)中的二维数组,同一条线上的点,会被累加到一起

3)取阈值,有多少个点在一条线上,则认为这是一条线

766aaab715614e49effa9d044e0414f4.png

2.代码实现(代码是我以前自学图像处理时写的,代码很粗糙没做任何优化,但很好理解)

先用边缘检测生成图像,再hough变换

 //先用边缘检测生成图像,再hough变换
QImage* MainWindow:: HoughLine(QImage* image)
{
    double sinValue[360];
    double cosValue[360];
    int k = 100;
    double scale=1;
    int p = (int)(sqrt(double(image->width()*image->width() + image->height()*image->height())+1));
    QImage* newImage = new QImage(360,p,QImage::Format_ARGB32);
    QColor color;
    int houghbuf[360][p];

    memset(houghbuf,0,sizeof(int)*360*p);//必须清0
    for(int i = 0;i<360;i++)
    {
        sinValue[i] = sin(i*3.1415926/180);
        cosValue[i] = cos(i*3.1415926/180);
    }
    int tp;
    for(int y =0;y<image->height();y++)
    {
        for(int x =0;x<image->width();x++)
        {
            color = QColor(image->pixel(x,y));
            for(int i = 0;i<360;i++)
            {
                if(color.red() > k)
                {
                    tp = (int)(x*sinValue[i] + y*cosValue[i]);
                    if(tp<0||houghbuf[i][tp]==255) continue;
                    houghbuf[i][tp]+=scale;
                }
            }
        }
    }
    for(int i = 0;i<360;i++)
    {
        for(int j = 0;j<p;j++)
        {
            newImage->setPixel(i,j,qRgb(houghbuf[i][j],houghbuf[i][j],houghbuf[i][j]));
        }
    }
    return newImage;
}

调用代码:

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QImage image;;
    image.load("E:/BaiduNetdiskDownload/imgeCode/xyl1.bmp");
    painter.drawImage(10,10, image);
    QImage* image1 = greyScale(&image);
    QImage* image2 = HoughLine(SideSobeldiant(image1, 1, 0));
    painter.drawImage(270,10,*image2);
}

运行结果:

先用边缘检测生成图像,接着hough变换,再滤波,最后画出直线

//先用边缘检测生成图像,接着hough变换,再滤波,最后画出直线 ,其中k1取值3000
QImage* MainWindow:: DrawLine(QImage* image,QImage* image1,int k1)
{
    double sinValue[360];
    double cosValue[360];
    int k = 100;
    double scale=1;
    int p = (int)(sqrt(double(image->width()*image->width() + image->height()*image->height())+1));
    QImage* newImage = new QImage(360,p,QImage::Format_ARGB32);
    QColor color;
    int houghbuf[360][p];

    memset(houghbuf,0,sizeof(int)*360*p);//必须清0
    for(int i = 0;i<360;i++)
    {
        sinValue[i] = sin(i*3.1415926/180);
        cosValue[i] = cos(i*3.1415926/180);
    }
    int tp;
    for(int y =0;y<image->height();y++)
    {
        for(int x =0;x<image->width();x++)
        {
            color = QColor(image->pixel(x,y));
            for(int i = 0;i<360;i++)
            {
                if(color.red() > k)
                {
                    tp = (int)(x*sinValue[i] + y*cosValue[i]);
                    if(tp<0||houghbuf[i][tp]==255) continue;
                    houghbuf[i][tp]+=scale;
                }
            }
        }
    }
    for(int i = 0;i<360;i++)
    {
        for(int j = 0;j<p;j++)
        {
            newImage->setPixel(i,j,qRgb(houghbuf[i][j],houghbuf[i][j],houghbuf[i][j]));
        }
    }

    int tmplt[5][5]={
        {-2,-2,-2,-2,-2},
        {-2,0,4,0,-2},
        {-2,4,16,4,-2},
        {-2,0,4,0,-2},
        {-2,-2,-2,-2,-2}
    };
    int templtsize = 5;
    double kk,bb;
    int xx,yy;
    for(int x = 0;x<360;x++)
   {
      for(int y= 0;y<p;y++)
       {
           int r = 0;
           int g = 0;
           int b = 0;
           int px1 = 0;
           int py1 = 0;
           for(int i = 0;i<templtsize;i++)
           {
              for(int j = 0;j<templtsize;j++)
               {
                  py1=(y-templtsize/2+i+p)%p;
                  px1=(x-templtsize/2+j+360)%360;
                  color = QColor(newImage->pixel(px1,py1));
                  r+=color.red()*tmplt[i][j];
                  g+=color.green()*tmplt[i][j];
                  b+=color.blue()*tmplt[i][j];
               }
           }
           if(r>k1)
           {
               if(x!=90)
               {
                   bb = y/cos(x*3.1415926535/180);
                   kk = -sin(x*3.1415926535/180)/cos(x*3.1415926535/180);
                   yy =0;
                   xx =0;
                   if(abs(kk)<=1)
                   {
                       for(xx =0;xx<image->width();xx++)
                       {
                           yy=(int)(kk*xx+bb);
                           if(yy>=0 && yy<image->height())
                           {
                               r = 255;
                               g = 0;
                               b = 0;
                               image1->setPixel(xx,yy,qRgb( r,g,b));
                           }
                       }
                   }
                   else
                   {
                       for(yy =0;yy<image->height();yy++)
                       {
                           xx=(int)(yy/kk - bb/kk);
                           if(xx>=0 && xx<image->width())
                           {
                               r = 255;
                               g = 0;
                               b = 0;
                               image1->setPixel(xx,yy,qRgb( r,g,b));
                           }
                       }
                   }
               }
               else
               {
                   for(yy=0;yy<image->height();yy++)
                   {
                       r = 255;
                       g = 0;
                       b = 0;
                       image1->setPixel(x,yy,qRgb( r,g,b));
                   }
               }

           }
       }
   }
    delete newImage;
    return   image1;
}

调用代码:

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QImage image;;
    image.load("E:/BaiduNetdiskDownload/imgeCode/xyl1.bmp");
    painter.drawImage(10,10, image);
    QImage* image1 = greyScale(&image);
    QImage* image2 = DrawLine(SideSobeldiant(image1, 1, 0), &image, 1500);
    painter.drawImage(270,10,*image2);
}

运行结果:

导航