Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于Hough线变换的最长直线检测_C#_Image Processing_Hough Transform - Fatal编程技术网

C# 基于Hough线变换的最长直线检测

C# 基于Hough线变换的最长直线检测,c#,image-processing,hough-transform,C#,Image Processing,Hough Transform,我想用Hough变换在一幅图像中 输入图像 预期产量 当前输出 我们可以看到它检测到了错误的线路 在下面的代码中,我应该在哪里查找错误? 不过有一个陷阱。如果我将阈值从50增加到150,源代码似乎会产生正确的输出。但是,对我来说,这没有任何意义,因为增加门槛意味着排除投票率较低的队伍 源代码 HoughLineTransform.cs 公共类行 { 公共点开始{get;set;} 公共点结束{get;set;} 公共整数长度 { 收到 { return(int)Math.Sqrt(Mat

我想用Hough变换在一幅图像中

输入图像

预期产量

当前输出

我们可以看到它检测到了错误的线路

在下面的代码中,我应该在哪里查找错误?

不过有一个陷阱。如果我将阈值从50增加到150,源代码似乎会产生正确的输出。但是,对我来说,这没有任何意义,因为增加门槛意味着排除投票率较低的队伍

源代码

HoughLineTransform.cs

公共类行
{
公共点开始{get;set;}
公共点结束{get;set;}
公共整数长度
{
收到
{
return(int)Math.Sqrt(Math.Pow(End.X-Start.X,2)+Math.Pow(End.Y-Start.Y,2));
}
}
公共电话线()
{
}
公共线路(点起点、点终点)
{
开始=开始;
结束=结束;
}
}
公共类HoughLineTransform
{
公共HoughMap累加器{get;set;}
公共HoughLineTransform(){}
公共线路GetLongestLine()
{
列表行=获取行(50);
int maxIndex=0;
double maxLength=-1.0;
对于(int i=0;i阈值)
{
//这是一个局部极大值(9x9)
int峰值=累加器[rho,θ];
对于(int-ly=-4;ly=0&&lx+theta峰值)
{
峰值=累加器[rho+ly,θ+lx];
ly=lx=5;
}
}
}
}
中频(峰值>(整数)累加器[rho,θ])
持续
int-x1,y1,x2,y2;
x1=y1=x2=y2=0;
双rad=θ*Math.PI/180;

如果(θ>=45&&θ该算法实际上很容易理解,即使乍一看也是如此。 它基于以下行公式:

式中,ρ是从原点到直线的垂直距离,θ是该垂直线与水平轴形成的角度

如果你知道ρ和θ,你就知道这条线。如果你取所有可能的对(在给定的精度范围内) 对于ρ和θ,你实际上得到了所有可能存在于图像中的线,这就是为什么
Map[ρ,θ]
存储。如果希望角度的精度为1度,则需要180列。对于ρ,最大可能的距离是图像的对角线长度。因此,采用一个像素的精度,行数可以是图像的对角线长度。但是不是 图像,正方形(在HoughMap.cs中):

doubleHoughHeight
是正方形的对角线,这就是为什么需要
Math.Max

图像的每个点都映射到地图阵列上:

阈值过滤掉小于50点的行。以下代码也过滤掉行:

//Is this point a local maxima (9x9)
int peak = Accumulator[ rho, theta ];

for( int ly = -4; ly <= 4; ly++ ) {
    for( int lx = -4; lx <= 4; lx++ ) {
        if( ( ly + rho >= 0 && ly + rho < houghWidth ) && ( lx + theta >= 0 && lx + theta < houghHeight ) ) {
            if( (int)Accumulator[ rho + ly, theta + lx ] > peak ) {
                peak = Accumulator[ rho + ly, theta + lx ];
                    ly = lx = 5;
             }
         }
     }
 }

 if( peak > (int)Accumulator[ rho, theta ] )
     continue;
//这是一个局部极大值(9x9)
int峰值=累加器[rho,θ];
对于(int-ly=-4;ly=0&&lx+theta峰值){
峰值=累加器[rho+ly,θ+lx];
ly=lx=5;
}
}
}
}
中频(峰值>(整数)累加器[rho,θ])
持续
您的实际问题可以在以下图像中看到:

得到的端点和起点实际上是直线和两个轴的交点:

int x1, y1, x2, y2;
x1 = y1 = x2 = y2 = 0;

double rad = theta * Math.PI / 180;

if( theta >= 45 && theta <= 135 ) {
    //y = (r - x Math.Cos(t)) / Math.Sin(t)
    x1 = 0;
    y1 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( x1 - ( imageWidth / 2 ) ) * Math.Cos( rad ) ) ) / Math.Sin( rad ) + ( imageHeight / 2 ) );
    x2 = imageWidth - 0;
    y2 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( x2 - ( imageWidth / 2 ) ) * Math.Cos( rad ) ) ) / Math.Sin( rad ) + ( imageHeight / 2 ) );
}
else {
    //x = (r - y Math.Sin(t)) / Math.Cos(t);
    y1 = 0;
    x1 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( y1 - ( imageHeight / 2 ) ) * Math.Sin( rad ) ) ) / Math.Cos( rad ) + ( imageWidth / 2 ) );
    y2 = imageHeight - 0;
    x2 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( y2 - ( imageHeight / 2 ) ) * Math.Sin( rad ) ) ) / Math.Cos( rad ) + ( imageWidth / 2 ) );
}

lines.Add( new Line( new Point( x1, y1 ), new Point( x2, y2 ) ) );
intx1,y1,x2,y2;
x1=y1=x2=y2=0;
双rad=θ*Math.PI/180;

如果(θ>=45&&θ该算法实际上很容易理解,即使乍一看也是如此。 它基于以下行公式:

式中,ρ是从原点到直线的垂直距离,θ是该垂直线与水平轴形成的角度

如果你知道ρ和θ,你就知道这条线。如果你取所有可能的对(在给定的精度范围内) 对于ρ和θ,你实际上得到了所有可能存在于图像中的线,这就是为什么
Map[ρ,θ]
存储。如果希望角度的精度为1度,则需要180列。对于ρ,最大可能的距离是图像的对角线长度。因此,采用一个像素的精度,行数可以是图像的对角线长度。但是不是 图像,正方形(在HoughMap.cs中):

doubleHoughHeight
是正方形的对角线,这就是为什么需要
Math.Max

图像的每个点都映射到地图阵列上:

threshold过滤掉小于50点的行
int maxTheta = 180;
int houghHeight = (int)( Math.Sqrt( 2 ) * Math.Max( imgWidth, imgHeight ) ) / 2;
int doubleHoughHeight = houghHeight * 2;
     ρ                      θ    number of points in that line( pair (ρ, θ) )
Map  0                      0    num0
     0                      1    num1
     0                      2    num2
     .                      .    .
     .                      .    .
     doubleHoughHeight – 1  179  numN
//Is this point a local maxima (9x9)
int peak = Accumulator[ rho, theta ];

for( int ly = -4; ly <= 4; ly++ ) {
    for( int lx = -4; lx <= 4; lx++ ) {
        if( ( ly + rho >= 0 && ly + rho < houghWidth ) && ( lx + theta >= 0 && lx + theta < houghHeight ) ) {
            if( (int)Accumulator[ rho + ly, theta + lx ] > peak ) {
                peak = Accumulator[ rho + ly, theta + lx ];
                    ly = lx = 5;
             }
         }
     }
 }

 if( peak > (int)Accumulator[ rho, theta ] )
     continue;
int x1, y1, x2, y2;
x1 = y1 = x2 = y2 = 0;

double rad = theta * Math.PI / 180;

if( theta >= 45 && theta <= 135 ) {
    //y = (r - x Math.Cos(t)) / Math.Sin(t)
    x1 = 0;
    y1 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( x1 - ( imageWidth / 2 ) ) * Math.Cos( rad ) ) ) / Math.Sin( rad ) + ( imageHeight / 2 ) );
    x2 = imageWidth - 0;
    y2 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( x2 - ( imageWidth / 2 ) ) * Math.Cos( rad ) ) ) / Math.Sin( rad ) + ( imageHeight / 2 ) );
}
else {
    //x = (r - y Math.Sin(t)) / Math.Cos(t);
    y1 = 0;
    x1 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( y1 - ( imageHeight / 2 ) ) * Math.Sin( rad ) ) ) / Math.Cos( rad ) + ( imageWidth / 2 ) );
    y2 = imageHeight - 0;
    x2 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( y2 - ( imageHeight / 2 ) ) * Math.Sin( rad ) ) ) / Math.Cos( rad ) + ( imageWidth / 2 ) );
}

lines.Add( new Line( new Point( x1, y1 ), new Point( x2, y2 ) ) );
public List<Point>[] lstPnts { get; set; }

public void Compute() {
    if( Image != null ) {
        ...
        ...
        ...
        Map = new int[ doubleHoughHeight, maxTheta ];

        //Add this code////////////////////////////////////////////////
        //lstPnts is an doubleHoughHeight * maxTheta size array of list Points
        lstPnts = new List<Point>[ doubleHoughHeight * maxTheta ];

        for(int i = 0; i < doubleHoughHeight * maxTheta; i++ ) {
            lstPnts[ i ] = new List<Point>();
        }
        ///////////////////////////////////////////////////////////////
        ....
        ....
        ....
        if( ( rho > 0 ) && ( rho <= Map.GetLength( 0 ) ) ) {
            Map[ rho, theta ]++;
            //Add this line of code////////////////////////////////////////
            lstPnts[ rho * maxTheta + theta ].Add( new Point( x, y ) );
            ///////////////////////////////////////////////////////////////
            PointsCount++;
        }
        ....
    }
}
public List<Line> GetLines( int threshold ) {
    if( Accumulator == null ) {
        throw new Exception( "HoughMap is null" );
    }

    int houghWidth = Accumulator.Width;
    int houghHeight = Accumulator.Height;
    int imageWidth = Accumulator.Image.GetLength( 0 );
    int imageHeight = Accumulator.Image.GetLength( 1 );

    List<Line> lines = new List<Line>();

    if( Accumulator == null )
        return lines;

    for( int rho = 0; rho < houghWidth; rho++ ) {
        for( int theta = 0; theta < houghHeight; theta++ ) {
            if( (int)Accumulator[ rho, theta ] > threshold ) {
                //Is this point a local maxima (9x9)
                int peak = Accumulator[ rho, theta ];
                int dd = 10;

                for( int ly = -dd; ly <= dd; ly++ ) {
                    for( int lx = -dd; lx <= dd; lx++ ) {
                        if( ( ly + rho >= 0 && ly + rho < houghWidth ) && ( lx + theta >= 0 && lx + theta < houghHeight ) ) {
                            if( (int)Accumulator[ rho + ly, theta + lx ] > peak ) {
                                peak = Accumulator[ rho + ly, theta + lx ];
                                ly = lx = dd + 1;
                            }
                        }
                    }
                }

                if( peak > (int)Accumulator[ rho, theta ] )
                    continue;

                //Map[ rho, theta ] contains these points -> lstPnts[ rho * houghHeight + theta ].
                //The points in that list with min and max X coordinate are the Start and End ones
                int x1 = houghWidth, y1 = 0, x2 = -1, y2 = 0;

                for(int i = 0; i < Accumulator.lstPnts[ rho * houghHeight + theta ].Count; i++ ) {
                    if( Accumulator.lstPnts[ rho * houghHeight + theta ][ i ].X > x2 ) {
                        x2 = Accumulator.lstPnts[ rho * houghHeight + theta ][ i ].X;
                        y2 = Accumulator.lstPnts[ rho * houghHeight + theta ][ i ].Y;
                    }

                    if( Accumulator.lstPnts[ rho * houghHeight + theta ][ i ].X < x1 ) {
                        x1 = Accumulator.lstPnts[ rho * houghHeight + theta ][ i ].X;
                        y1 = Accumulator.lstPnts[ rho * houghHeight + theta ][ i ].Y;
                    }
                }


                //Remove this code
                /*int x1, y1, x2, y2;
                x1 = y1 = x2 = y2 = 0;

                double rad = theta * Math.PI / 180;

                if( theta >= 45 && theta <= 135 ) {
                    //y = (r - x Math.Cos(t)) / Math.Sin(t)
                    x1 = 0;
                    y1 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( x1 - ( imageWidth / 2 ) ) * Math.Cos( rad ) ) ) / Math.Sin( rad ) + ( imageHeight / 2 ) );
                    x2 = imageWidth - 0;
                    y2 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( x2 - ( imageWidth / 2 ) ) * Math.Cos( rad ) ) ) / Math.Sin( rad ) + ( imageHeight / 2 ) );
                }
                else {
                    //x = (r - y Math.Sin(t)) / Math.Cos(t);
                    y1 = 0;
                    x1 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( y1 - ( imageHeight / 2 ) ) * Math.Sin( rad ) ) ) / Math.Cos( rad ) + ( imageWidth / 2 ) );
                    y2 = imageHeight - 0;
                    x2 = (int)( ( (double)( rho - ( houghWidth / 2 ) ) - ( ( y2 - ( imageHeight / 2 ) ) * Math.Sin( rad ) ) ) / Math.Cos( rad ) + ( imageWidth / 2 ) );
                }*/

                lines.Add( new Line( new Point( x1, y1 ), new Point( x2, y2 ) ) );
            }
        }
    }

    return lines;
}