題目要求:
魔術方塊,六種顏色以文字表之。
圖片共十二張:
點我下載
##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";
}
}
}
}