我花了几个小时研究这个并且我已经取得了一些进展但仍需要一些帮助。
我知道有些库可以做到这一点,但由于我的场景非常简单,我宁愿拥有自己的代码。我在支票扫描仪中扫描支票,但有些图像弯曲,需要去掉;
这是我的代码:
Function DeskewImage(Original As Bitmap) As Bitmap
Dim w = Original.Width
Dim h = Original.Height
'i go over the first 200 rows of pixels and for each row i get the first black pixel. this should be enough to get me the angle
Dim FirstBlacks As New List(Of Point)
For row = 0 To 200
For col = 0 To w - 1
Dim p = Original.GetPixel(col, row)
Dim rl = CInt(p.R) + p.G + p.B
If rl < 760 Then
FirstBlacks.Add(New Point(col, row))
Exit For
End If
Next
Next
'here i try to get the angle, im not sure its correct though
Dim xyAvg = FirstBlacks.Select(Function(pnt) pnt.X * pnt.Y).Average
Dim xAvg = FirstBlacks.Select(Function(pnt) pnt.X).Average
Dim yAvg = FirstBlacks.Select(Function(pnt) pnt.Y).Average
Dim xVar = FirstBlacks.Select(Function(pnt) pnt.X).Variance
Dim coefficient = (xyAvg - xAvg * yAvg) / xVar
Dim LeftTop = -20
'now id like utilize the angle to skew
Dim destinationPoints = {New Point(0, LeftTop), New Point(w, 0), New Point(0, h)}
Dim ret = New Bitmap(w, h)
Dim g = Graphics.FromImage(ret)
g.DrawImage(Original, destinationPoints)
ret.Save("D:\aa.jpg")
Return Original
End Function
我有两个问题:
我也觉得很奇怪,我需要指定高度&amp;绘图前返回图像的宽度。我怎么知道歪斜之前的大小?
修改
感谢Pieter Geerkens我将代码更改为旋转而不是倾斜
问题现在仍然存在于算法
中首先是一个样本图像
我上面的算法返回了大约-0.33这个样本图片的结果。实际上我需要大约+4度旋转。算法错了吗?或者结果是否需要转换为度?任何想法?
欣赏
答案 0 :(得分:1)
尝试更改destinationPoints的分配,如下所示:
Dim dh = coefficient * h
Dim dw = coefficient * w
Dim destinationPoints = {
New Point(0, LeftTop),
New Point(w,-dw),
New Point(dh, h)
}
根据以下OP说明进行更新:
对于小角度θ(以弧度表示),θ~sin(θ)~tan(θ)。因此,旋转角度(以度为单位)约为1(180 / PI)*系数* w / w =(180 / PI)*系数。
答案 1 :(得分:0)
行。感谢http://www.alcula.com/calculators/statistics/linear-regression/我能够调试我的算法结果。这个工具帮我发现我实际上正在混合xs和ys。正确的代码如下。
我也不得不忽略低x值,这实际上是左边界,而不是顶边。
Dim ret As Double?
Dim w = Original.Width
Dim h = Original.Height
Dim FirstBlacks = New List(Of Point)
Dim MaxHeight = h - 1
Dim done = False
For y = 0 To MaxHeight
If done Then Exit For
For x = 0 To w - 1
Dim p = Original.GetPixel(x, y)
Dim rl = p.GetBrightness
If rl < 1 Then
If x < 20 Then
done = True
Else
FirstBlacks.Add(New Point(x, y))
End If
Exit For
End If
Next
Next
If FirstBlacks.Count > 2 Then
Dim xyAvg = FirstBlacks.Select(Function(pnt) pnt.X * pnt.Y).Average
Dim xAvg = FirstBlacks.Select(Function(pnt) pnt.X).Average
Dim yAvg = FirstBlacks.Select(Function(pnt) pnt.Y).Average
Dim xVar = FirstBlacks.Select(Function(pnt) pnt.X).Variance
ret = (xyAvg - xAvg * yAvg) / xVar
End If
Return ret
感谢Pieter-Geerkens一路上的所有帮助