Visual Basic 中的滞后阈值
Hysteresis thresholding in visual basic
我正在尝试在 visual basic 中为精明的边缘检测制作滞后阈值。由于我是这个主题的新手和 vb 的新手(我主要使用 php),我阅读的许多参考资料都指出我需要这样做。由于图像已经是黑白的,我只得到一种颜色的强度。我已经在几秒钟内完成了高斯模糊、灰度、索贝尔蒙版和非极大值抑制。但是在滞后上,执行该功能的时间太长了。我不知道我哪里做错了。如果有帮助,图像为 640 x 480。我尝试将分辨率更改为更小的分辨率,它确实更快但我想将分辨率保持为 640 x 480。我已经更改了代码,这是我的最终方法
Dim bmp_thres As New Bitmap(pic_nonmaxima)
Dim visited_maps As New List(Of String)
Dim threshold_H As Integer = 100
Dim threshold_L As Integer = 50
Dim Ycount As Integer
For Ycount = 1 To bmp_thres.Height - 2
Dim Xcount As Integer
For Xcount = 1 To bmp_thres.Width - 2
'check current pointer
Dim currPointer As String = Xcount & "," & Ycount
'find if coordinate visited already
Dim find_array As String
If visited_maps IsNot Nothing Then
find_array = visited_maps.Contains(currPointer)
Else
find_array = "False"
End If
If find_array Then
'if existed, do nothing
Else
'if not, do something
Dim currThreshold As Integer
Dim currColor As Color
currColor = bmp_thres.GetPixel(Xcount, Ycount)
currThreshold = currColor.R
'add coordinate into visited maps
Dim visited As String = Xcount & "" & Ycount
visited_maps.Add(visited)
If currThreshold > threshold_H Then
bmp_thres.SetPixel(Xcount, Ycount, Color.FromArgb(255, 255, 255))
Else
bmp_thres.SetPixel(Xcount, Ycount, Color.FromArgb(0, 0, 0))
'check connectedness
Dim coord_N As String = Xcount & "," & Ycount + 1
Dim coord_E As String = Xcount + 1 & "," & Ycount
Dim coord_S As String = Xcount & "," & Ycount - 1
Dim coord_W As String = Xcount - 1 & "," & Ycount
Dim coord_NE As String = Xcount + 1 & "," & Ycount + 1
Dim coord_SE As String = Xcount + 1 & "," & Ycount - 1
Dim coord_SW As String = Xcount - 1 & "," & Ycount - 1
Dim coord_NW As String = Xcount - 1 & "," & Ycount + 1
Dim myCoord As New List(Of String)
myCoord.Add(coord_N)
myCoord.Add(coord_E)
myCoord.Add(coord_S)
myCoord.Add(coord_W)
myCoord.Add(coord_NE)
myCoord.Add(coord_SE)
myCoord.Add(coord_SW)
myCoord.Add(coord_NW)
For Each coord In myCoord
If Not visited_maps.Contains(coord) Then
'Split by ,
Dim split_Coord() As String = Split(coord, ",")
'check thres on coord
Dim coordColor As Color = bmp_thres.GetPixel(split_Coord(0), split_Coord(1))
Dim coordThres As Integer = coordColor.R
If coordThres > threshold_H Then
bmp_thres.SetPixel(split_Coord(0), split_Coord(1), Color.FromArgb(255, 255, 255))
Else
bmp_thres.SetPixel(split_Coord(0), split_Coord(1), Color.FromArgb(0, 0, 0))
End If
End If
visited_maps.Add(coord)
Next 'end if foreach
End If ' end if checking current threshold
End If 'end if find coord in visited maps
Next 'end for xcount
Next 'end for ycount
Return bmp_thres
或者,如果您发现我做的一些错误代码,请向我指出。
如果我做对了,当我们做滞后阈值时,我们首先检查坐标是否已经被访问过,如果它被访问过我们检查下一个坐标。如果不是,我们将坐标添加到访问的地图中,如果当前坐标大于阈值高,我们将像素值更改为白色,否则为黑色。然后我们检查连通性,如果它们通过低阈值,我们将像素值更改为白色,否则为黑色。然后我们将所有的连通性添加到访问过的地图中。重复。
我可以做些什么来减少时间?或者请指出我的错误。任何帮助将不胜感激。对不起,如果你不明白英语。这将有助于我的最后一年项目 T_T
我认为这可能是 Code Review 的主题,因为它正在运行(尽管速度很慢)。但以防万一,我将把它留在这里作为部分答案。
您的坐标搜索有一个小错误。不管它是否已经在 visited_maps
中你仍然添加它,这将在列表中产生很多额外的结果。
If Not visited_maps.Contains(coord) Then
' YOUR CODE
End If
visited_maps.Add(coord)
此行:visited_maps.Add(coord)
需要在 If
内,这样您就不会有重复值将您的列表扩展到超出需要的范围。一张 640 * 480 像素的图像会在您的列表中创建超过 300,000 个条目,并且由于这个坐标错误,它还会有更多。
List
可能也不是最合适的类型,像 HashSet
这样的类型更好,因为您不需要按索引访问。看看 What is the difference between HashSet and List?
当您调用 Color.FromArgb(255, 255, 255)
时,您每次都在创建一个新的 Color
对象。这将再次至少有 300 000 个对象,当您可以在顶部声明一个黑色实例和另一个白色实例,然后根据需要使用它们时。
我不确定在逗号分隔字符串上使用 Point
结构会有什么性能差异,但它会节省很多 splitting/concatenation 并且更易读.
Dim currPointer As String = Xcount & "," & Ycount
Dim coord_N As String = Xcount & "," & Ycount + 1
会变成
Dim currPointer As Point = New Point(Xcount, Ycount)
Dim coord_N as Point = New Point(currPointer.X, currPointer.Y + 1)
还有更多错误,但它们很小,所以我暂时将它们关闭
我正在尝试在 visual basic 中为精明的边缘检测制作滞后阈值。由于我是这个主题的新手和 vb 的新手(我主要使用 php),我阅读的许多参考资料都指出我需要这样做。由于图像已经是黑白的,我只得到一种颜色的强度。我已经在几秒钟内完成了高斯模糊、灰度、索贝尔蒙版和非极大值抑制。但是在滞后上,执行该功能的时间太长了。我不知道我哪里做错了。如果有帮助,图像为 640 x 480。我尝试将分辨率更改为更小的分辨率,它确实更快但我想将分辨率保持为 640 x 480。我已经更改了代码,这是我的最终方法
Dim bmp_thres As New Bitmap(pic_nonmaxima)
Dim visited_maps As New List(Of String)
Dim threshold_H As Integer = 100
Dim threshold_L As Integer = 50
Dim Ycount As Integer
For Ycount = 1 To bmp_thres.Height - 2
Dim Xcount As Integer
For Xcount = 1 To bmp_thres.Width - 2
'check current pointer
Dim currPointer As String = Xcount & "," & Ycount
'find if coordinate visited already
Dim find_array As String
If visited_maps IsNot Nothing Then
find_array = visited_maps.Contains(currPointer)
Else
find_array = "False"
End If
If find_array Then
'if existed, do nothing
Else
'if not, do something
Dim currThreshold As Integer
Dim currColor As Color
currColor = bmp_thres.GetPixel(Xcount, Ycount)
currThreshold = currColor.R
'add coordinate into visited maps
Dim visited As String = Xcount & "" & Ycount
visited_maps.Add(visited)
If currThreshold > threshold_H Then
bmp_thres.SetPixel(Xcount, Ycount, Color.FromArgb(255, 255, 255))
Else
bmp_thres.SetPixel(Xcount, Ycount, Color.FromArgb(0, 0, 0))
'check connectedness
Dim coord_N As String = Xcount & "," & Ycount + 1
Dim coord_E As String = Xcount + 1 & "," & Ycount
Dim coord_S As String = Xcount & "," & Ycount - 1
Dim coord_W As String = Xcount - 1 & "," & Ycount
Dim coord_NE As String = Xcount + 1 & "," & Ycount + 1
Dim coord_SE As String = Xcount + 1 & "," & Ycount - 1
Dim coord_SW As String = Xcount - 1 & "," & Ycount - 1
Dim coord_NW As String = Xcount - 1 & "," & Ycount + 1
Dim myCoord As New List(Of String)
myCoord.Add(coord_N)
myCoord.Add(coord_E)
myCoord.Add(coord_S)
myCoord.Add(coord_W)
myCoord.Add(coord_NE)
myCoord.Add(coord_SE)
myCoord.Add(coord_SW)
myCoord.Add(coord_NW)
For Each coord In myCoord
If Not visited_maps.Contains(coord) Then
'Split by ,
Dim split_Coord() As String = Split(coord, ",")
'check thres on coord
Dim coordColor As Color = bmp_thres.GetPixel(split_Coord(0), split_Coord(1))
Dim coordThres As Integer = coordColor.R
If coordThres > threshold_H Then
bmp_thres.SetPixel(split_Coord(0), split_Coord(1), Color.FromArgb(255, 255, 255))
Else
bmp_thres.SetPixel(split_Coord(0), split_Coord(1), Color.FromArgb(0, 0, 0))
End If
End If
visited_maps.Add(coord)
Next 'end if foreach
End If ' end if checking current threshold
End If 'end if find coord in visited maps
Next 'end for xcount
Next 'end for ycount
Return bmp_thres
或者,如果您发现我做的一些错误代码,请向我指出。
如果我做对了,当我们做滞后阈值时,我们首先检查坐标是否已经被访问过,如果它被访问过我们检查下一个坐标。如果不是,我们将坐标添加到访问的地图中,如果当前坐标大于阈值高,我们将像素值更改为白色,否则为黑色。然后我们检查连通性,如果它们通过低阈值,我们将像素值更改为白色,否则为黑色。然后我们将所有的连通性添加到访问过的地图中。重复。
我可以做些什么来减少时间?或者请指出我的错误。任何帮助将不胜感激。对不起,如果你不明白英语。这将有助于我的最后一年项目 T_T
我认为这可能是 Code Review 的主题,因为它正在运行(尽管速度很慢)。但以防万一,我将把它留在这里作为部分答案。
您的坐标搜索有一个小错误。不管它是否已经在 visited_maps
中你仍然添加它,这将在列表中产生很多额外的结果。
If Not visited_maps.Contains(coord) Then
' YOUR CODE
End If
visited_maps.Add(coord)
此行:visited_maps.Add(coord)
需要在 If
内,这样您就不会有重复值将您的列表扩展到超出需要的范围。一张 640 * 480 像素的图像会在您的列表中创建超过 300,000 个条目,并且由于这个坐标错误,它还会有更多。
List
可能也不是最合适的类型,像 HashSet
这样的类型更好,因为您不需要按索引访问。看看 What is the difference between HashSet and List?
当您调用 Color.FromArgb(255, 255, 255)
时,您每次都在创建一个新的 Color
对象。这将再次至少有 300 000 个对象,当您可以在顶部声明一个黑色实例和另一个白色实例,然后根据需要使用它们时。
我不确定在逗号分隔字符串上使用 Point
结构会有什么性能差异,但它会节省很多 splitting/concatenation 并且更易读.
Dim currPointer As String = Xcount & "," & Ycount
Dim coord_N As String = Xcount & "," & Ycount + 1
会变成
Dim currPointer As Point = New Point(Xcount, Ycount)
Dim coord_N as Point = New Point(currPointer.X, currPointer.Y + 1)
还有更多错误,但它们很小,所以我暂时将它们关闭