标准霍夫变换识别粗直线
Posted lc__________
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了标准霍夫变换识别粗直线相关的知识,希望对你有一定的参考价值。
在项目中需要识别粗直线。
正常来讲对于直线的识别需要对图像进行边缘检测,再对边缘检测后的图像进行概率霍夫变换。但是对于存在粗直线的图像,边缘检测后,粗直线非边缘的部分就被过滤掉了,有效信息会有部分丢失,且opencv中霍夫变换的效果不太理想,以至于对于两条边缘直线的合并就更加困难了。因此想对霍夫线变换进行改进。
概率霍夫变换效率高于标准霍夫变换,而且可以找到线段的两个端点,是一般大家用的比较多的方法。
概率霍夫变换会沿着直线的方向继续寻找直线上的点,以确定线段的两个端点。但是在粗直线中,这不方便被表示,因此选用了更耗时的标准霍夫变换。
opencv中实现霍夫变换的步骤如下:
1.对边缘图像进行霍夫变换
2.对霍夫空间进行4领域内的非最大值抑制
3.对极大值进行排序,极值越大,则越有可能是直线
4.输出直线
我的改进:
1.不对图像进行边缘检测。直接对二值图像中的黑色像素点进行霍夫变换
2.非最大值抑制对于粗直线来说没有太大意义,因此不进行非最大值抑制,直接对霍夫变换后的结果进行排序
我用的是VB.net + EmguCv
Sub ThickLineHoughLinesStandard(ByVal img As Image(Of Gray, Byte),
ByVal rho As Double,
ByVal theta As Double,
ByVal threshold As Integer,
ByRef output As ArrayList)
Dim width As Integer = img.Width
Dim height As Integer = img.Height
Dim numangle, numrho As Integer
Dim total As Integer = 0
Dim irho As Double = 1 / rho
Dim scale As Double
numangle = Int(Math.PI / theta)
numrho = Int(((img.Width + img.Height) * 2 + 1) / rho)
Dim accum((numangle + 2) * (numrho + 2)) As Integer
Dim sort_buf(numangle * numrho) As Integer
Dim ang As Double = 0.0
Dim tabSin As Hashtable = New Hashtable
Dim tabCos As Hashtable = New Hashtable
'为避免重复运算,事先计算好sinθi/ρ和cosθi/
For n = 0 To numangle - 1
tabSin(n) = Math.Sin(ang) * irho
tabCos(n) = Math.Cos(ang) * irho
ang += theta
Next
'执行步骤1,逐点进行霍夫变换,并把结果放入累加器中
For i = 0 To height - 1
For j = 0 To width - 1
'只对图像的非零值进行处理,即只对图像的边缘像素进行霍夫变换
If img.Data(i, j, 0) = 0 Then
For n = 0 To numangle - 1
Dim r As Integer = Math.Floor(j * tabCos(n) + i * tabSin(n))
r += (numrho - 1) / 2
accum((n + 1) * (numrho + 2) + r + 1) = accum((n + 1) * (numrho + 2) + r + 1) + 1
Next
End If
Next
Next
'执行步骤2,找到局部极大值
For r = 0 To numrho - 1
For n = 0 To numangle - 1
Dim base As Integer = (n + 1) * (numrho + 2) + r + 1
If accum(base) > threshold Then
sort_buf(total) = base
total += 1
End If
Next
Next
'执行步骤3,对存储再sort_buf数组内的累加器的数据由大到小进行排序
Dim sortBaseHashtable As New Hashtable
Dim sortAccumHashtable As New Hashtable
Dim sortArray As New ArrayList
For s = 0 To total - 1
sortBaseHashtable(s) = sort_buf(s)
sortAccumHashtable(s) = accum(sort_buf(s))
sortArray.Add(accum(sort_buf(s)))
Next
sortArray.Sort()
Dim outputSortBuf(sortArray.Count - 1) As Integer
Dim outputSortCount As Integer = 0
For s = sortArray.Count - 1 To 0 Step -1
For Each a In sortAccumHashtable
If Val(sortArray(s)) = Val(a.value) Then
outputSortBuf(outputSortCount) = sortBaseHashtable(s)
outputSortCount += 1
sortAccumHashtable.Remove(Int(a.key))
Exit For
End If
Next
Next
'执行步骤4,输出直线
scale = 1.0 / (numrho + 2)
For i = 0 To total - 1
Dim line As New Line
'idx为极大值在累加器数组的位置
Dim idx As Integer = outputSortBuf(i)
'分离出该极大值在霍夫空间中的位置
Dim n As Integer = Math.Floor(idx * scale - 1)
Dim r As Integer = idx - (n + 1) * (numrho + 2) - 1
'最终得到极大值所对应的角度和距离
line.rho = (r - (numrho - 1) * 0.5F) * rho
line.angle = n * theta
output.Add(line)
Next
End Sub
ThickLineHoughLinesStandard(img, 1, Math.PI / 15.0, 200, output)
For Each Line In output
Dim a As Double = Math.Cos(Line.angle)
Dim b As Double = Math.Sin(Line.angle)
Dim x0 As Double = a * Line.rho
Dim y0 As Double = b * Line.rho
Dim k As New LineSegment2D
k.P1 = New Point(x0 + 2000 * (-b) + 20, y0 + 2000 * a + 50)
k.P2 = New Point(x0 - 2000 * (-b) + 20, y0 - 2000 * a + 50)
outputImg.Draw(k, New Bgr(Color.Red), 1)
Next
outputImg.Save(Application.StartupPath + "\\img\\output.bmp")
最终输出的直线中,角度相同,rho连续的直线组合成了我想要找到的粗直线~
以上是关于标准霍夫变换识别粗直线的主要内容,如果未能解决你的问题,请参考以下文章
Python OpenCV 霍夫(Hough Transform)直线变换检测原理,图像处理第 33 篇博客
opencv —— HoughLinesHoughLinesP 霍夫线变换(标准霍夫线变换多尺度霍夫线变换累积概率霍夫线变换)