# 北軟100 pD 辨識圖中的阿拉伯數字 ###### tags: `北軟100` ## 題目 方法:請觀察下面數字 :請觀察下面數字 0~9 圖形的最左邊一欄 0~9 圖形的最左邊一欄或是最底邊之特徵,每一個數字最左邊一欄 ,每一個數字最左邊一欄或是最底邊黑點的位置及數量均不同。請用其中一種特徵來辨識是哪一個數字。 ![](https://i.imgur.com/uKzLMTY.png) 實作:為簡化程式的撰 :為簡化程式的撰寫,僅以 32x32 的 BMP 圖檔為實作對象,BMP 圖上任一點在 BMP 圖檔 上是用 3Bytes(藍、綠、紅)存放,若是白點則存放著 255、255、255,若是黑點則存放著 0、0、0。本題目所附的 BMP 圖檔是由黑色的點組成。 本題目特別規定 BMP 圖左下角座標為(0, 0)、右下角座標為(31, 0)、左上角座標為(0, 31)、 右上角座標為(31, 31),如下左圖所示。 ![](https://i.imgur.com/VEcXZ16.png) BMP 圖檔的第 0、1 位元組一定是存放 42h、4Dh(h 表十六進位),如上右圖所示。 第 12h∼15h 位元組存放圖面寬的點數(32 點),第 16h∼19h 位元組存放圖面高的點數(32 點)。 第 0036h∼38h 位元組存放點座標(0,0)的藍、綠、紅之值為 0、0、0 表示一個黑點。 第 0039h∼3bh 位元組存放點座標(1,0)的藍、綠、紅之值為 255、255、255 表示一個白點。 第 0093h∼95h 位元組存放點座標(31, 0)的藍、綠、紅之值為 0、0、0 表示一個黑點。 第 0bd6h∼0bd8h 位元組存放點座標(0, 31)的藍、綠、紅之值為 0、0、0 表示一個黑點。 第 0c33h∼0c35h 位元組存放點座標(31, 31)的藍、綠、紅之值為 0、0、0 表示一個黑點。 請寫一支程式能辨識出 32x32 的 BMP 圖中的阿拉伯數字, 並將辨識結果顯示出來,如下圖所示。(20 分含操作介面 3 分) ![](https://i.imgur.com/PgkeAKt.png) 阿拉伯數字不在 32x32 的 BMP 圖的正中間也要能辨識出來,如下圖所示。(3 分) ![](https://i.imgur.com/eNUBVTs.png) 圖中阿拉伯數字最左邊一欄的特徵不符前面所定的方法,請顯示 “無法辨識” ,如下圖所示。(2 分) ![](https://i.imgur.com/8WBxXCO.png) ## 想法 由於最左邊一欄的特徵不符合也要偵測,選擇偵測的最好方法當然是偵測字形最左邊的邊緣。 我們先從圖像的最左邊開始進行掃描,依次每一pixel的直行由上往下掃描。 直到某個直行出現了黑點,即為字形的最左邊邊緣。 觀察題目給的圖示,為高度21的圖示。 接下來,我們針對於該直行的每21個pixel做掃描, 由於圖像只有黑色和白色,我們可以將它陳述為0與1。 我們可以觀察題目給的圖示,每個字元最左邊的邊緣一定是獨一無二的(這很難看出來,請仔細觀看) 將每個圖示的邊緣用0與1陳述。 0 為 000000111111111000000 1 為 001000000000000000001 2 為 000001000000000000001 3 為 000100000000000000010 4 為 000000000000001100000 5 為 000000010000000000100 6 為 000000000111111100000 7 為 000011000000000000000 8 為 000111100000001111000 9 為 000011111100000000001 接下來,我們在掃描的過程中,一旦發現了**完全**符合上面21個bit的結果,即可確定圖示為哪個字元。 ## 程式碼(C#) ```csharp= using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace problemD { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string path = textBox1.Text; Bitmap bmp = new Bitmap(path); pictureBox1.Image = bmp; int readLine = -1; for(int i = 0; i < bmp.Width && readLine == -1; i++) { for(int j = 0; j < bmp.Height && readLine == -1; j++) { if(bmp.GetPixel(i,j).R == 0) { readLine = i; } } } string[] array = { "000000111111111000000", "001000000000000000001", "000001000000000000001", "000100000000000000010", "000000000000001100000", "000000010000000000100", "000000000111111100000", "000011000000000000000", "000111100000001111000", "000011111100000000001" }; int number = -1; for (int i = 0; i < bmp.Height - 21; i++) { string str = ""; for (int j = i; j < i + 21; j++) { str += bmp.GetPixel(readLine, j).R == 0 ? "1" : "0"; } for(int j = 0; j < array.Length; j++) { if(str == array[j]) { number = j; } } Console.WriteLine(str); } if(number == -1) { textBox2.Text = "無法辨識"; return; } textBox2.Text = number + ""; } } } ```