0

私はこれを調査するのに数時間を費やし、ある程度の進歩を遂げましたが、まだ助けが必要です.

これを行うためのライブラリがあることは承知していますが、私のシナリオは非常に単純であるため、独自のコードを作成したいと考えています。小切手スキャナーで小切手をスキャンしていますが、一部の画像が曲がっているため、歪みを補正する必要があります。

これが私のコードです:

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

2 つの問題があります。

  1. 私の係数は正しいですか?これはhttp://www.experts-exchange.com/Microsoft/Development/MS_Access/A_2799-Simple-Linear-Regression-in-MS-Access.htmlの記事に基づいていました が、正しく移植したかどうかはわかりません
  2. 係数を利用して .net で画像を歪ませるにはどうすればよいですか? 私が見つけることができる唯一の機能は目的地ポイントを必要としますが、それを見つける方法がわかりません

また、描画する前に戻り画像の高さと幅を指定する必要があるのも奇妙です。スキュー前のサイズを知るにはどうすればよいですか?

編集

Pieter Geerkens のおかげで、コードを傾斜ではなく回転に変更しました

問題はアルゴリズムに残っています

まずはサンプル画像ですサンプル

上記の私のアルゴリズムは、このサンプル写真に対して約 -0.33 の結果を返します。実際には、約 +4 度の回転が必要です。アルゴリズムが間違っているのでしょうか?または、結果を度数に変換する必要がありますか? 何か案は?

感謝を込めて

4

2 に答える 2

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(シータ) です。したがって、回転角度 (度単位) は、およそ (180/PI) * 係数 * w / w = (180/PI) * 係数です。

于 2013-03-20T11:19:26.270 に答える
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に感謝します

于 2013-03-22T10:34:23.660 に答える