ゼロラーニング(笑)による7セグLED数字画像認識 その4
昨日の続きです。深層どころか、何も学習しないで(ゼロラーニング)画像から数字を画像認識するコードをVisualBasicで作っています。書いたコードはこんな感じ。コントロール名は昨日の日記参照。職業プログラマでもないし、試行錯誤しながら作ったのでちょっと汚い(ムダな部分がある)です。----------------------------------------Imports System.DrawingImports System.Windows.FormsPublic Class Form1'****************** '7セグの解析 Private Sub BT_Analyze7seg_Click() Handles BT_Analyze7seg.Click 'まずは画像を取得 'Bitmapの作成 画面のサイズで作る Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height) 'Graphicsの作成 Dim g As Graphics = Graphics.FromImage(bmp) '画面全体のスクリーンショットを取る(この時点ではまだカラー) g.CopyFromScreen(New Point(100, 100), New Point(0, 0), bmp.Size) '第一引数の座標を変えるとトリミングになる 上と左の100ドット切ってある 'グレースケールに変換 Dim grayImg As Image = CreateGrayscaleImage(bmp) '必要なら白黒反転 If CB_ImageInv.Checked = True Then grayImg = CreateNegativeImage(grayImg) '解析用画像を作る Dim img As New Bitmap(grayImg) '-------------------------------------------------------- '解析スタート Dim SegNumber As Integer 'いま解析しているセグメントの番号 Dim DotSize As Integer = TB_DotSize.Text '平均化エリアのドットサイズ Dim Thres As Integer = TB_Thres.Text '白黒判別のしきい値 Dim xxx, yyy, centerX, centerY As Integer '回している座標 Dim bbb As Integer '平均化エリアの強度値 Dim SegOnOffValue As Integer '点灯しているセグメントで作ったビット列みたいな整数 'seg1を10000の位、seg2を1000の位、seg3を100の位、seg4を10の位、seg5を10の位にした整数 Dim ResultValue As String '解析して判別した整数 Dim DecimalPoint As String '小数点があればピリオドが入る '点灯状態を調べる6つのセグメント点の座標 Dim Xpos(6) As Integer Dim Ypos(6) As Integer 'テキストボックスから座標を読み込む テキストボックスの名前はTB_seg○x.text等にしてある For SegNumber = 1 To 6 Xpos(SegNumber) = CType(Me.Controls("TB_seg" & SegNumber & "x"), TextBox).Text Ypos(SegNumber) = CType(Me.Controls("TB_seg" & SegNumber & "y"), TextBox).Text Next SegNumber '7の字形選択 Dim SevenOnOffValue As Integer If CB_seg1onFor7.Checked = True Then SevenOnOffValue = 10101 Else SevenOnOffValue = 101 End If'結果が入る変数を初期化 SegOnOffValue = 0 DecimalPoint = "" TB_FinalResult.Text = "" '------------- 'セグメントごとに明るさを調べる まずは文字部分の5セグメントの点灯・不点灯をを判別 For SegNumber = 1 To 5 '中心座標をセット centerX = Xpos(SegNumber) centerY = Ypos(SegNumber) '強度を初期化 bbb = 0 '平均化エリア内の強度の和を求める ついでに色付けする For xxx = centerX + DotSize * -1 To centerX + DotSize For yyy = centerY + DotSize * -1 To centerY + DotSize bbb = bbb + img.GetPixel(xxx, yyy).R.ToString img.SetPixel(xxx, yyy, Color.Yellow) Next yyy Next xxx '平均化したエリアのドット数で割って平均強度にする bbb = CInt(bbb / (DotSize * 2 + 1) ^ 2) 'もし強度がしきい値を超えていたら点灯しているとみなす 'そのセグメントの桁数に相当するビットを立たせる If bbb >= Thres Then SegOnOffValue = SegOnOffValue + 10 ^ (5 - SegNumber)Next SegNumber'------------- '文字の判別 ResultValue = "0" 'どれにも当てはまらないのはゼロにする Select Case SegOnOffValue Case 1 ResultValue = "1" Case 1111 ResultValue = "2" Case 111 ResultValue = "3" Case 10011 ResultValue = "4" Case 10110 ResultValue = "5" Case 11110 ResultValue = "6" Case SevenOnOffValue ResultValue = "7" Case 11111 ResultValue = "8" Case 10111 ResultValue = "9" Case 10 ResultValue = "-" End Select '------------- '小数点の判別 SegNumber = 6 '中心座標をセット、強度を初期化 centerX = Xpos(SegNumber) centerY = Ypos(SegNumber) bbb = 0 '平均化エリア内の強度の和を求める ついでに色付けする For xxx = centerX + DotSize * -1 To centerX + DotSize For yyy = centerY + DotSize * -1 To centerY + DotSize bbb = bbb + img.GetPixel(xxx, yyy).R.ToString img.SetPixel(xxx, yyy, Color.Yellow) Next yyy Next xxx bbb = CInt(bbb / (DotSize * 2 + 1) ^ 2) 'しきい値を超えていたら小数点をつける If bbb >= Thres Then DecimalPoint = "." '------------- '最終結果をまとめる '数字と小数点を付けてテキストボックスに入れる TB_FinalResult.Text = ResultValue & DecimalPoint 'イメージをピクチャボックスに転送 PictureBox1.Image = img End Sub'-----------------------------------------------------------------------------------'グレイスケールに変換する関数 DOBON.NETそのまま 'https://dobon.net/vb/dotnet/graphics/grayscale.html Public Shared Function CreateGrayscaleImage(ByVal img As Image) As Image 'グレースケールの描画先となるImageオブジェクトを作成 Dim newImg As New Bitmap(img.Width, img.Height) 'newImgのGraphicsオブジェクトを取得 Dim ggg As Graphics = Graphics.FromImage(newImg) 'ColorMatrixオブジェクトの作成 'グレースケールに変換するための行列を指定する 1行目がRの比率、2秒目はGの比率、3行目はBの比率 'https://dobon.net/vb/dotnet/graphics/colorbalance.html 'ここではYIQのYコンポーネントを利用 Dim cm As New System.Drawing.Imaging.ColorMatrix( New Single()() { New Single() {0.299F, 0.299F, 0.299F, 0, 0}, New Single() {0.587F, 0.587F, 0.587F, 0, 0}, New Single() {0.114F, 0.114F, 0.114F, 0, 0}, New Single() {0, 0, 0, 1, 0}, New Single() {0, 0, 0, 0, 1} }) 'ImageAttributesオブジェクトの作成 Dim ia As New System.Drawing.Imaging.ImageAttributes() 'ColorMatrixを設定する ia.SetColorMatrix(cm) 'ImageAttributesを使用してグレースケールを描画 ggg.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia) 'リソースを解放する ggg.Dispose() Return newImg End Function ' 指定された画像を白黒反転する DOBON.NETそのまま 'https://dobon.net/vb/dotnet/graphics/drawnegativeimage.html Public Shared Function CreateNegativeImage(ByVal img As Image) As Image 'ネガティブイメージの描画先となるImageオブジェクトを作成 Dim negaImg As New Bitmap(img.Width, img.Height) 'negaImgのGraphicsオブジェクトを取得 Dim g As Graphics = Graphics.FromImage(negaImg) 'ColorMatrixオブジェクトの作成 Dim cm As New System.Drawing.Imaging.ColorMatrix() 'ColorMatrixの行列の値を変更して、色が反転されるようにする cm.Matrix00 = -1 cm.Matrix11 = -1 cm.Matrix22 = -1 cm.Matrix33 = 1 cm.Matrix40 = 1 cm.Matrix41 = 1 cm.Matrix42 = 1 cm.Matrix44 = 1 'ImageAttributesオブジェクトの作成 Dim ia As New System.Drawing.Imaging.ImageAttributes() 'ColorMatrixを設定する ia.SetColorMatrix(cm) 'ImageAttributesを使用して色が反転した画像を描画 g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia) 'リソースを解放する g.Dispose() Return negaImg End Function'----------------------------------------------------------------------------------- 'クリックした点の座標をフォーカスのあるテキストボックスに入力Private Sub PictureBox1_Click(sender As Object, e As MouseEventArgs) Handles PictureBox1.Click 'フォーカスのあるコントロールの名前の6文字目を取得 'セグメントの座標を示すテキストボックスの名前はTB_seg○x.textにしてあるから6文字目を取得 Dim selectedTextBoxName As String = Me.ActiveControl.Name.Substring(6, 1) '数字に変換できれば、seg1~6の座標を示すテキストボックスにフォーカスがあると判断 Dim selectedTextBoxNumber As Integer Try selectedTextBoxNumber = CInt(selectedTextBoxName) 'エラーが出れば数字にできなかった=座標のテキストボックスではなかったとして抜ける Catch ex As Exception Exit Sub End Try 'クリックした点の座標をテキストボックスに入れる CType(Me.Controls("TB_seg" & selectedTextBoxNumber & "x"), TextBox).Text = e.X CType(Me.Controls("TB_seg" & selectedTextBoxNumber & "y"), TextBox).Text = e.Y '画像キャプチャ&解析を走らせる BT_Analyze7seg_Click() End SubEnd Classセグメントの点灯状態を表す整数を、8ビットのビット列にしてしまえばもうちょっと効率的でしょう。また、小数点の判別は別ループでやっていますが、数字と同じループで書けると思います(小数点だけ後から追加したからこうなった)まあ、いろいろ試行錯誤しながら作ってますから。とりあえずプリンでも食いましょう。父の日 ギフト プレゼント もりん プレミアム プリン 極濃 送料無料 6個入 ギフト おもてなし とろふわ とろとろ ふわとろ 人気 洋菓子明日に続く。