Kernel-based Hough transform (KHT)移植

来源:互联网 发布:oracle数据库保存 编辑:程序博客网 时间:2024/06/12 00:16

  • Kernel-based Hough transform KHT移植
    • 简介
    • 分析程序
    • 移植到自己程序中并用OpenCV画出检测出的直线
    • 附录 KHTOpenCV测试程序

Kernel-based Hough transform (KHT)移植

本周发现了一篇讲解可以很大程度加快霍夫变换的论文,并且已经有实现好的例程了,所以想试下看以后能不能用的上,算法名字叫Kernel-based Hough transform (KHT)。暂时还没看懂,不过经过试验,在我电脑上(i3-2310M)对于2560x1920的图像找出直线大约需要70ms,对比下一直使用的OpenCV的标准算法大约需要200ms,release版本只需要20ms,OpenCV release版本需要110ms

简介:

Fernandes and Oliveira1suggested an improved voting scheme for the Hough transform that allows a software implementation to achieve real-time performance even on relatively large images (e.g., 1280×960). The Kernel-based Hough transform uses the same (r,\theta ) parameterization proposed by Duda and Hart but operates on clusters of approximately collinear pixels. For each cluster, votes are cast using an oriented elliptical-Gaussian kernel that models the uncertainty associated with the best-fitting line with respect to the corresponding cluster. The approach not only significantly improves the performance of the voting scheme, but also produces a much cleaner accumulator and makes the transform more robust to the detection of spurious lines.2

该项目在SourceForge中公布源代码
下载链接:
http://iweb.dl.sourceforge.net/project/khtsandbox/khtsandbox/KHT%20Sandbox%201.0.2/kht_sandbox-1.0.2-source.zip
http://kht-sandbox.soft112.com/
下载解压后共三个文件夹

  • kht_source中是kst算法的源码
  • matlab中是matlab使用示例
  • sample_app中是使用示例

sample_app中的工程可以用vs2010打开转换下,sample_app_vc++9.sln和sample_app_vc++8.sln都可以转换成功(我只有vs2010,更低版本的应该也可以)
但工程属性需要改一下

  • 常规->输出目录$(SolutionDir)$(Configuration)\
  • 常规->中间目录$(Configuration)$\
  • 链接器->输出文件$(OutDir)$(TargetName)$(TargetExt)
  • 切换到Debug状态时还要再改一遍

这里写图片描述
默认是Release 状态, Ctrl+F5运行下,结果很好:图像大小为800x800左右,帧率依次为25,28,27,30,34,40,35,40

这里写图片描述
这里写图片描述
这里写图片描述

分析程序:

测试程序是用OpenIL(不过现在又叫DevIL,不懂)来读取图像的,原图是单色位图,但是读进来后一个像素还是一个字节的,我用一张小图片测试了一下,像素在数组中的位置还是从左到右,从上到下的。和OpenCV一样。所有图像读取后都存到images_list中,最重要的变换函数是

kht( lines, image->pixels_copy, image->width, image->height, 10, 2.0, 0.5, 0.002, 2 );

不过貌似这个函数会更改输入图像,全部置0,所以需要提前备份一份。
得到的每条直线的rho和theta,theta不是弧度制的,所以后面有一句将角度转成弧度制。

double theta = line.theta * deg_to_rad;

需要注意的是:求得的rho和theta是以图像中心为坐标原点的,用OpenCV画直线时需要转化一下。
画直线是用OpenGL和Glut实现的,OpenGL也是以图像中心为坐标原点的,所以最左下角的点的坐标为(-w/2,-h/2), 最右上角的点的坐标为(w/2,h/2)。

glBegin( GL_LINES ); //就是开始画直线了glVertex2d( -aux, (line.rho + aux * cos_theta) * one_div_sin_theta );//给定第一个端点glVertex2d( aux, (line.rho - aux * cos_theta) * one_div_sin_theta );//给定第二个端点

画线这一段原理是利用式1,直线上的所有点(x,y)都满足式1,解方程,再将x=-w/2和x=w/2带入求得两个端点。

xcosθ+ysinθ=ρ

y=ρxcosθsinθ

w2=w2,x1=w2,y1=ρ+w2cosθsinθ

x2=w2,y1=ρw2cosθsinθ

移植到自己程序中并用OpenCV画出检测出的直线

移植到自己程序中只需将kht_source文件夹复制到自己程序文件夹内,并添加到工程中,在主函数前面包括进kht.h。

#include "./kht_source/kht.h"

复制要处理的图像数据,调用kht函数就可以了

Mat img_copy = img.clone();static lines_list_t lines;kht( lines, img_copy.data, img.cols, img.rows, 10, 2.0, 0.5, 0.002, 2 );

绘制直线就比较麻烦了,OpenCV的坐标原点是左上角,要做坐标变换。
设OpenGL中点的坐标为(x,y),OpenCV中点的坐标为(u,v),则:

u=x+w/2,v=h/2y

但测试时发现还是出错#待解决,程序中实际情况是
u=x+w/2,v=h/2+y

整体测试程序见附录,但是测试building_binary.bmp时出现问题,该图画出的直线和原来的示例不同。#待解决
这里写图片描述

附录 KHT+OpenCV测试程序

// HoughLineTest.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <stdio.h>#include <iostream>#include <time.h>#include "./kht_source/kht.h"#include <opencv2/opencv.hpp>using namespace cv;#define mymin(x,y) (x<y?x:y)#ifndef PI#define PI 3.14#endif void drawline(Mat& imgs,vector<Point2f>& linesl);void drawline(Mat& imgs,lines_list_t& lines);int _tmain(int argc, _TCHAR* argv[]){    // Load input binary images.    static const size_t images_count = 8;    static const char *filenames[images_count]       = {"./images/chess_binary.bmp", "./images/road_binary.bmp", "./images/wall_binary.bmp", "./images/board_binary.bmp", "./images/church_binary.bmp", "./images/building_binary.bmp", "./images/beach_binary.bmp", "./images/simple_binary.bmp" };    static const size_t relevant_lines[images_count] = {25,                          15,                         36,                         38,                          40,                           19,                             19,                          8                            };    int test_flag = 0;    while(test_flag)    {        Mat img = imread(filenames[0],0);        Mat img_copy = img.clone();        static lines_list_t lines;        //vector<Point2f> lines;        time_t time_start,time_stop;        time_start = clock();        kht( lines, img_copy.data, img.cols, img.rows, 10, 2.0, 0.5, 0.002, 2 );        //HoughLines(img_copy, lines, 1, CV_PI/180, 140, 0, 0 );        time_stop = clock();        std::cout<<time_stop-time_start<<std::endl;    }    for (size_t i=0; i!=images_count; ++i)    {        Mat img = imread(filenames[i],0);        if(img.channels()==1)        {            Mat img_copy = img.clone();            static lines_list_t lines;            kht( lines, img_copy.data, img.cols, img.rows, 10, 2.0, 0.5, 0.002, 2 );//          vector<Point2f> lines;//           HoughLines(img_copy, lines, 1, CV_PI/180, 130, 0, 0 );            drawline(img,lines);        }    }    return 0;}void drawline(Mat& imgs,vector<Point2f>& lines){    Mat imgl;    cvtColor(imgs,imgl,CV_GRAY2BGR);    for( size_t i=0,linenum=mymin(25,lines.size());i<linenum; i++ )    {        float rho = lines[i].x, theta = lines[i].y;        Point pt1, pt2;        double a = cos(theta), b = sin(theta);        double x0 = a*rho, y0 = b*rho;        pt1.x = cvRound(x0 + 2000*(-b));        pt1.y = cvRound(y0 + 2000*(a));        pt2.x = cvRound(x0 - 2000*(-b));        pt2.y = cvRound(y0 - 2000*(a));        cv::line( imgl, pt1, pt2, cvScalar(0,0,255), 1, CV_AA);    }       imshow("Horize HoughLines",imgl);    waitKey();}void drawline(Mat& imgs,lines_list_t& lines){    Mat imgl;    cvtColor(imgs,imgl,CV_GRAY2BGR);    if(lines.size())    {        for( size_t i=0,linenum=mymin(25,lines.size());i<linenum; i++ )        {            line_t &line = lines[i];            Point pt1,pt2;            if(line.theta != 0.0)            {                 int w2 = imgl.cols/2;                int h2 = imgl.rows/2;                static const double deg_to_rad = PI/ 180.0;                double theta = line.theta * deg_to_rad;                double rho = line.rho;                double cos_theta = cos( theta );                double one_div_sin_theta = 1 / sin( theta );                pt1.x = 0;                pt1.y = h2 + (line.rho + w2 * cos_theta) * one_div_sin_theta ;                pt2.x = w2+w2;                pt2.y = h2 + (line.rho - w2 * cos_theta) * one_div_sin_theta ;                cv::line( imgl, pt1, pt2, cvScalar(0,0,250), 1, CV_AA);             }            else            {                int w2 = imgl.cols/2;                int h2 = imgl.rows/2;                pt1.x = w2 + line.rho;                pt1.y = 0;                pt2.x = w2 + line.rho;                pt2.y = h2+h2;                cv::line( imgl, pt1, pt2, cvScalar(0,0,250), 1, CV_AA);             }        }       }    imshow("Horize HoughLines",imgl);    waitKey();}


  1. [1]:Fernandes L A F, Oliveira M M. Real-time line detection through an improved Hough transform voting scheme[J]. Pattern Recognition, 2008, 41(1):299-314.
    [2]: https://en.wikipedia.org/wiki/Hough_transform ↩
  2. [1]:Fernandes L A F, Oliveira M M. Real-time line detection through an improved Hough transform voting scheme[J]. Pattern Recognition, 2008, 41(1):299-314.
    [2]: https://en.wikipedia.org/wiki/Hough_transform ↩
0 0
原创粉丝点击