 |
By: Lord Nikon
March 27, 2006
Well, this OCR function is much faster than GetPixel in my C# OCR version, and this works very well. This is the main code I did, you can easily turn it into a function if you like. I will go over each part in a second.
void dBox(int X, int Y)
{
if (X != 0 && Y != 0)
{
Bitmap^ OBJBox = gcnew Bitmap(picCaptcha->Image);
OBJBox->SetPixel(X - 2, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 1, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 1, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y + 1, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y - 1, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 1, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 1, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y - 1, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y + 1, System::Drawing::Color::Black);
picCaptcha->Image= gcnew Bitmap(OBJBox);
}
else { MessageBox::Show("The fed X or Y coordinate(s) are out of range"); }
}
private: System::Void cmdGetDarkPixel_Click(System::Object^ sender, System::EventArgs^ e)
{
int X = 25;
int Y = 25;
Bitmap^ OBJPic = gcnew Bitmap(picCaptcha->Image);
Color Brightest = System::Drawing::Color::White;
Color colCur;
Boolean IsBlack = false;
for (int curX = 0; curX < OBJPic->Width && IsBlack == false; curX += System::Convert::ToInt32(txtXStep->Text))
{
for (int curY = 0; curY < OBJPic->Height && IsBlack == false; curY += System::Convert::ToInt32(txtYStep->Text))
{
colCur = OBJPic->GetPixel(curX,curY);
if (colCur.GetBrightness() < Brightest.GetBrightness())
{
Brightest = colCur;
X = curX;
Y = curY;
IsBlack = (Brightest == System::Drawing::Color::Black);
}
}
}
dBox(X, Y);
lblResults->Text="Found X: " + X + " Found Y: " + Y;
}
private: System::Void picCaptcha_MouseMove(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e)
{
lblStats->Text = "Current X: " + e->X + " Current Y: " + e->Y;
}
private: System::Void cmdLoadNew_Click(System::Object^ sender, System::EventArgs^ e)
{
String^ strPath;
OpenNew->ShowDialog();
strPath = OpenNew->FileName;
picCaptcha->Image= gcnew Bitmap(strPath);
}
And in case it comes in handy, here's the Namespace imports:
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Runtime::InteropServices;

The main part of the program is bascially this 'for' loop:
int X = 25;
int Y = 25;
Bitmap^ OBJPic = gcnew Bitmap(picCaptcha->Image);
Color Brightest = System::Drawing::Color::White;
Color colCur;
Boolean IsBlack = false;
for (int curX = 0; curX < OBJPic->Width && IsBlack == false; curX += 4
{
for (int curY = 0; curY < OBJPic->Height && IsBlack == false; curY += 4
{
colCur = OBJPic->GetPixel(curX,curY);
if (colCur.GetBrightness() < Brightest.GetBrightness())
{
Brightest = colCur;
X = curX;
Y = curY;
IsBlack = (Brightest == System::Drawing::Color::Black);
}
}
}
1. The first part gets the bitmap of the picture box, and assigns it to the Bitmap object called "OBJPic".
2. The second part declares a variable called "colBrightest" and assigns the color black to it. I know it's not the brightest color, but it's simply called that because a color can't get any darker than black; so as soon the the scanner gets a pixel that's black it'll stop because nothing can get darker than black itself.
3. If you know much about C++ for loops then you can tell I got two 'for' loops to scan every pixel of the picture while the the X and Y coords are in range with the picture's height and width and while the current pixel is not black (although it will stop once it finds a black pixel).
4. Now, hard coded inside the 'for' loop, we assign current pixel's color to a color variable called colColor. If the brightness of the current color is lower than the brightness of black then black becomes the color of the current color and we assign proper values to the X and Y variables.
5. This step is pretty simple, bascially if current color is black then 'IsBlack' becomes true and the 'for' loops will stop.
Well, thats pretty much what the function does. It is slow, but you can make more efficient coding by different means, which I will post later.
After you have aquired the right coordinates, you can use this dBox function to draw a small box arround the found pixel:
void dBox(int X, int Y)
{
if (X != 0 && Y != 0)
{
Bitmap^ OBJBox = gcnew Bitmap(picCaptcha->Image);
OBJBox->SetPixel(X - 2, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 1, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 1, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y + 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y + 1, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y - 1, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 2, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X + 1, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 1, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y - 2, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y - 1, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y, System::Drawing::Color::Black);
OBJBox->SetPixel(X - 2, Y + 1, System::Drawing::Color::Black);
picCaptcha->Image= gcnew Bitmap(OBJBox);
}
else { MessageBox::Show("The fed X or Y coordinate(s) are out of range"); }
}
Note: Both 'for' loops step by 4, which means that every 4 pixels will be scanned. If there are 24 pixels in one line and the X Step is 4 then out of the 24 pixels only 6 pixels will be scanned. This causes the program to be less accurate but much faster because it scans less pixels. You can always make it more accurate by stepping by 1 instead.
I also coded up a VB6 equivalent of this program.
Features:
* Set X Step
* Set Y Step
* Download from Internet using Internet Explorer cookies
* Show X and Y Coordinates on Mouseover on the picture
* Load Picture from the Computer
* Shows Time taken to find the Pixel
Disadvantages:
* Uses the GetPixel method of the BitMap class so it is very slow.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Dark_Pixel
{
public partial class frmMain : Form
{
[DllImport("winmm.dll")]
private static extern long timeGetTime();
long t;
public frmMain()
{
InitializeComponent();
}
private void cmdLoadPic_Click(object sender, EventArgs e)
{
string strPath;
Loader.ShowDialog();
strPath = Loader.FileName;
picCaptcha.Image = new Bitmap(strPath);
}
public void dBox(PictureBox Picture, int X,int Y,Color BoxColor)
{
Bitmap OBJBox;
// Load the picture into a bitmap object
OBJBox = new Bitmap(Picture.Image);
OBJBox.SetPixel(X - 2, Y + 2, BoxColor);
OBJBox.SetPixel(X - 1, Y + 2, BoxColor);
OBJBox.SetPixel(X, Y + 2, BoxColor);
OBJBox.SetPixel(X + 1, Y + 2, BoxColor);
OBJBox.SetPixel(X + 2, Y + 2, BoxColor);
OBJBox.SetPixel(X + 2, Y + 1, BoxColor);
OBJBox.SetPixel(X + 2, Y, BoxColor);
OBJBox.SetPixel(X + 2, Y - 1, BoxColor);
OBJBox.SetPixel(X + 2, Y - 2, BoxColor);
OBJBox.SetPixel(X + 1, Y - 2, BoxColor);
OBJBox.SetPixel(X, Y - 2, BoxColor);
OBJBox.SetPixel(X - 1, Y - 2, BoxColor);
OBJBox.SetPixel(X - 2, Y - 2, BoxColor);
OBJBox.SetPixel(X - 2, Y - 1, BoxColor);
OBJBox.SetPixel(X - 2, Y, BoxColor);
OBJBox.SetPixel(X - 2, Y + 1, BoxColor);
BoxColor = OBJBox.GetPixel(X, Y);
//Load the edited Picture into the Picturebox
Picture.Image = new Bitmap(OBJBox);
}
private void cmdLoadInet_Click(object sender, EventArgs e)
{
if (txtURL.Text == "")
{
MessageBox.Show("Enter an Image URL please");
}
picCaptcha.LoadAsync(txtURL.Text);
}
private void cmdFind_Click(object sender, EventArgs e)
{
t = timeGetTime();
int X, Y;
Color colBrightest = Color.White;
Color colCur;
Boolean IsBlack = false;
Bitmap OBJPic;
X = 0;
Y = 0;
OBJPic=new Bitmap(picCaptcha.Image);
for (int curX = 0; curX < OBJPic.Width && IsBlack == false; curX++)
{
for (int curY = 0; curY < OBJPic.Height && IsBlack == false; curY++)
{
colCur = OBJPic.GetPixel(curX, curY);
if (colCur.GetBrightness() < colBrightest.GetBrightness())
{
colBrightest = colCur;
X = curX;
Y = curY;
IsBlack = (colBrightest == Color.Black);
}
curY = curY + Convert.ToInt16(intYStep.Text);
}
curX = curX + Convert.ToInt16(intXStep.Text);
}
intX.Text = Convert.ToString(X);
intY.Text = Convert.ToString(Y);
switch (txtColor.Text)
{
case "Black":
dBox(picCaptcha, X, Y, Color.Black);
break;
case "Red":
dBox(picCaptcha, X, Y, Color.Red);
break;
case "Green":
dBox(picCaptcha, X, Y, Color.Green);
break;
case "Blue":
dBox(picCaptcha, X, Y, Color.Blue);
break;
case "White":
dBox(picCaptcha, X, Y, Color.White);
break;
}
t = timeGetTime() - t;
lblTime.Text = t + " MS";
}
private void frmMain_Load(object sender, EventArgs e)
{
txtColor.Text = "Black";
}
private void picCaptcha_MouseMove(object sender, MouseEventArgs e)
{
lblCurY.Text = Convert.ToString(e.Y);
label9.Text = Convert.ToString(e.X);
}
}
}
|
 |