魔術方塊,六種顏色以文字表之。
圖片共十二張:點我下載
##ReadMore##
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using AForge.Imaging.Filters; using AForge.Imaging.Formats; using AForge.Imaging; using System.Drawing.Imaging; using System.Diagnostics; using AForge.Math; namespace examination_e { public partial class Form1 : Form { Bitmap srcImg, cropImg, confirmImg; String knowColor; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { openFileDialog1.Filter = "All File(*.*)|*.*"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { srcImg = ImageDecoder.DecodeFromFile(openFileDialog1.FileName); pictureBox1.Image = srcImg; } } private void button2_Click(object sender, EventArgs e) { listBox1.Items.Clear(); //因為每張魔術方塊圖大小、位置不定,慢慢抓最大最小值縮減掃描範圍 int catchX = 250; int catchY = 130; int catchWidth = 650; int catchHeight = 500; //第一階段截取圖片,因為每張魔術方塊圖大小、位置不定先截個自訂值(畫 rectangle 慢慢測試得來的) Crop cropFilter = new Crop(new Rectangle(catchX, catchY, catchWidth, catchHeight)); Bitmap scanImg = cropFilter.Apply(srcImg); pictureBox3.Image = scanImg; Graphics g = Graphics.FromImage(srcImg); g.DrawRectangle(new Pen(Color.Red), catchX - 1, catchY - 1, catchWidth + 2, catchHeight + 2); pictureBox2.Image = srcImg; //Color 陣列用來儲存第一階段截取範圍內全部 colorPixel,容器 +10 避免誤差,造成超出陣列 Color[,] colorPixel = new Color[catchX + catchWidth + 10, catchY + catchHeight + 10]; //初始化,魔術方塊區域之座標最大、最小值 int max_x = 0, max_y = 0, min_x = catchX + catchWidth, min_y = catchY + catchHeight; //開始取得第一階段截取範圍全部的 colorPixel for (int i = catchX; i < catchX + catchWidth; i++) { for (int j = catchY; j < catchY + catchHeight; j++) { colorPixel[i, j] = srcImg.GetPixel(i, j); } } //掃描第一階段截取之範圍, 取得非黑色的座標之最大、最小座標 max_x, max_y, min_x, min_y for (int i = catchX; i < catchX + catchWidth; i++) { for (int j = catchY; j < catchY + catchHeight; j++) { // 設 RGB < 90 為黑色,非魔術方塊區域。 if (colorPixel[i, j].R < 90 && colorPixel[i, j].G < 90 && colorPixel[i, j].B < 90) { /*nothing to do*/ } // 第一層過濾,非黑色,則有可能是彩色圖,但有誤差,所以還要第二層過濾。 else { // 設 RGB < 90 為黑色,非魔術方塊區域。 if (colorPixel[i - 2, j - 2].R < 90 && colorPixel[i - 2, j - 2].G < 90 && colorPixel[i - 2, j - 2].B < 90) { /* nothing to do */ } //第二層過濾,判斷座標 [i-2, j-2] colorPixel 必需不是黑色 (即捕捉連續彩色→但只能捉到魔術方塊左上角座標,右下座標仍有誤差) else { // 設 RGB < 90 為黑色,非魔術方塊區域。 if (colorPixel[i + 2, j + 2].R < 90 && colorPixel[i + 2, j + 2].G < 90 && colorPixel[i + 2, j + 2].B < 90) { /* nothing to do */ } //第三層過濾,判斷座標 [i+2, j+2] colorPixel 必需不是黑色 (即捕捉連續彩色→測試後可以正確抓到魔術方塊完整範圍) else { // 抓魔術方塊區域之座標最大、最小值 if (max_x < i) max_x = i; if (max_y < j) max_y = j; if (min_x > i) min_x = i; if (min_y > j) min_y = j; } } } } } //得到魔術方塊區域之最大、最小座標 max_x, max_y, min_x, min_y,算差值得到魔術方塊之 Height= calcH, Width=calcW int calcW = max_x - min_x; int calcH = max_y - min_y; //做記號至 srcImg 測試確認用 g.DrawRectangle(new Pen(Color.Red), min_x, min_y, calcW, calcH); textBox1.Text = "BottomRight=(" + max_x + ", " + max_y + ")"; textBox2.Text = "TopLeft=(" + min_x + ", " + min_y + ")"; textBox3.Text = "width=" + calcW + ", height=" + calcH; //第二階段截取圖片,得到完整魔術方塊的區域 = cropImg Crop cropFilter2 = new Crop(new Rectangle(min_x, min_y, calcW, calcH)); cropImg = cropFilter2.Apply(srcImg); //魔術方塊的區域印至 pictureBox3 再確認 pictureBox3.Image = cropImg; /* //手動測試用 int jjj = 0; int iii = 2; Crop cropFilterTest = new Crop(new Rectangle(iii * calcW / 3, jjj * calcH / 3, calcW / 3, calcH / 3)); confirmImg = cropFilterTest.Apply(cropImg); pictureBox4.Image = confirmImg; */ //掃描魔術方塊區域 for (int jj = 0; jj < 3; jj++) { for (int ii = 0; ii < 3; ii++) { //第三階段截取,割成 3×3, 每一格單位: Width=calcH/3, Height=calcH/3,以 for-loop 掃描 Crop cropFilter3 = new Crop(new Rectangle(ii * calcW / 3, jj * calcH / 3, calcW / 3, calcH / 3)); confirmImg = cropFilter3.Apply(cropImg); //傳送單塊顏色中心點之 RGB 判別顏色 Color confirmPixel = confirmImg.GetPixel(confirmImg.Width / 2, confirmImg.Height / 2); //寫一個 function confirmColor 內有色表做顏色確認 confirmColor(confirmPixel.R, confirmPixel.G, confirmPixel.B); listBox1.Items.Add("(" + jj + ", " + ii + ") = " + knowColor); //listBox1.Items.Add("R,G,B = " +confirmPixel.R + "," + confirmPixel.G + "," + confirmPixel.B); listBox1.Items.Add(""); } listBox1.Items.Add("-----------------"); } pictureBox2.Image = srcImg; } public void confirmColor(int R, int G, int B) { //Blue if (R < 40 && G < 50 && B > 70 && B < 150) knowColor = "Blue"; //Yellow else if (R > 200 && G > 170 && B > 50 && B < 96) knowColor = "Yellow"; //Green else if (R < 80 && G > 50 && G < 160 && B > 40 && B < 100) knowColor = "Green"; //Orange else if (R > 175 && G > 55 && G < 115 && B < 68) knowColor = "Orange"; //Red else if (R > 100 && R < 200 && G < 55 && B < 50) knowColor = "Red"; //White else if (R > 170 && G > 179 && B > 170) knowColor = "White"; else { knowColor = "unknow"; } } } }
沒有留言:
張貼留言