实例介绍
【实例截图】
【核心代码】
// by conmajia
// 10 JUN, 2012
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using AForge.Imaging;
using System.Drawing;
using AForge.Imaging.Filters;
using AForge;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Imaging;
namespace QQValidationCodeRecognition
{
public partial class Form1 : Form
{
#region vars
// imagechar
List<ImageChar> imgChars;
// images
Bitmap srcImg = null;
Bitmap preImg = null;
// preprocess sequence
FiltersSequence preprocessFilters;
// histogram
int[] histo;
// histo ranges
IntRange[] ranges;
#endregion
#region Inits
public Form1()
{
InitializeComponent();
// stores
imgChars = new List<ImageChar>();
preprocessFilters = new FiltersSequence();
preprocessFilters.Add(Grayscale.CommonAlgorithms.BT709);
//preprocessFilters.Add(new BradleyLocalThresholding());
preprocessFilters.Add(new OtsuThreshold());
}
#endregion
#region Image helpers
Bitmap preprocess(Bitmap bmp, FiltersSequence fs)
{
Bitmap tmp = bmp.Clone() as Bitmap;
tmp = fs.Apply(bmp);
return tmp;
}
Bitmap projectHistogram(Bitmap bmp)
{
// stats
if (histo != null)
histo = null;
int width = bmp.Width;
int height = bmp.Height;
histo = new int[width];
for (int y = 0; y < height; y )
for (int x = 0; x < width; x )
{
Color color = bmp.GetPixel(x, y);
if (color.R < 50 && color.G < 50 && color.B < 50)
//if (color.A > 200)
histo[x] ;
}
// draw
//int max = getMax(histo);
Bitmap tmp = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(tmp))
for (int i = 0; i < width; i )
g.DrawLine(
Pens.Black,
i,
height,
i,
height - histo[i]);
return tmp;
}
// get rid of noises
Bitmap denoise(Bitmap bmp, Size size)
{
Bitmap ivbmp = bmp.Clone() as Bitmap;
Invert iv = new Invert();
iv.ApplyInPlace(ivbmp);
BlobCounter bc = new BlobCounter();
bc.FilterBlobs = true;
bc.MinWidth = bc.MinHeight = 0;
bc.MaxWidth = size.Width;
bc.MaxHeight = size.Height;
bc.ProcessImage(ivbmp);
Rectangle[] rects = bc.GetObjectsRectangles();
Bitmap tmp = new Bitmap(bmp);
using (Graphics g = Graphics.FromImage(tmp))
//g.DrawRectangles(Pens.Red, rects);
if (rects.Length > 0)
g.FillRectangles(Brushes.White, rects);
//iv.ApplyInPlace(tmp);
return tmp;
}
// draw some division lines over bitmap
Bitmap getRangedBitmap(Bitmap bmp, IntRange[] ranges)
{
Bitmap tmp = bmp.Clone() as Bitmap;
Graphics g = Graphics.FromImage(tmp);
for (int i = 0; i < ranges.Length; i )
{
g.DrawLine(
Pens.Purple,
ranges[i].Min,
0,
ranges[i].Min,
tmp.Height);
g.DrawLine(
Pens.Purple,
ranges[i].Max,
0,
ranges[i].Max,
tmp.Height);
}
return tmp;
}
#endregion
#region analyze helpers
int getMax(int[] array)
{
int max = 0;
foreach (int b in histo)
{
if (b > max)
max = b;
}
return max;
}
// TODO: optimize algorithm
IntRange[] getRanges(int[] data, int threshold, int min)
{
List<IntRange> tmp = new List<IntRange>();
int max = getMax(data);
threshold = (int)(threshold * max / (float)byte.MaxValue);
for (int i = 0; i < data.Length; i )
if (data[i] >= threshold)
for (int j = i; j < data.Length; j )
if (data[j] < threshold)
if (j - i >= min)
{
tmp.Add(new IntRange(i, j));
i = j - 1;
break;
}
// calculate average width
if (tmp.Count > 0)
{
int total = tmp[tmp.Count - 1].Max - tmp[0].Min;
float aver = (float)total / (float)tmp.Count;
List<IntRange> newtmp = new List<IntRange>(tmp);
int rcount = tmp.Count;
for (int i = 0; i < rcount; i )
{
// devide large into small
if (tmp[i].Length > 1.8 * aver)
{
int count = (int)(tmp[i].Length / aver) 1;
for (int j = 0; j < count; j )
{
int offset = (int)(tmp[i].Min j * aver);
IntRange r = new IntRange(offset, offset (int)aver);
tmp.Insert(i, r);
}
tmp.RemoveAt(i);
}
}
}
return tmp.ToArray();
}
#endregion
#region UI helpers
// clear all
void clearAll()
{
foreach (Control c in this.Controls)
{
if (c is PictureBox && c.Name != "pictureBox1")
(c as PictureBox).Image = null;
}
histo = null;
}
#endregion
#region ctrls
// Load image
private void loadImgLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
srcImg = AForge.Imaging.Image.FromFile(ofd.FileName);
}
catch
{
}
if (srcImg != null)
{
clearAll();
srcPic.Image = srcImg;
}
}
}
//******************
// analyze image
private void recognizeButton_Click(object sender, EventArgs e)
{
if (srcImg == null)
return;
// clear
srcPic.Image = null;
// rotate
srcPic.Image = srcImg;
// preprocess
int noiseWidth = (int)noiseNumeric.Value;
preImg = denoise(preprocess(srcPic.Image as Bitmap, preprocessFilters), new Size(noiseWidth, noiseWidth));
preImg = denoise(preprocess(preImg, preprocessFilters), new Size(noiseWidth, 3));
preImg = denoise(preprocess(preImg, preprocessFilters), new Size(3, noiseWidth));
prePic.Image = preImg;
// histogram
histoPic.Image = projectHistogram(prePic.Image as Bitmap);
}
// picture box click, send to check pic
private void picClick(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
checkPic.Image = pb.Image;
// get ranges
ranges = getRanges(histo, histoPic.Threshold, 2);
rangeLabel.Text = string.Format(
"Range:{0}",
ranges.Length);
// divide
divideCharPic.Image = getRangedBitmap(preImg, ranges);
}
// change color of check pic
private void checkColorClick(object sender, EventArgs e)
{
Control c = sender as Control;
checkPic.BackColor = c.BackColor;
}
private void invertCheckBox_CheckedChanged(object sender, EventArgs e)
{
// simple remove
if (preprocessFilters.Count == 3)
preprocessFilters.RemoveAt(2);
else
preprocessFilters.Add(new Invert());
recognizeButton_Click(null, null);
}
// mouse moves over histogram, updates the threshold label
private void histoPic_MouseMove(object sender, MouseEventArgs e)
{
thresholdLabel.Text = string.Format(
"阈值:{0}",
histoPic.Threshold);
}
#endregion
}
#region ImageChar class
public class ImageChar
{
Bitmap img = null;
public Bitmap Image
{
get { return img; }
set { img = value; }
}
char ch;
public char Char
{
get { return ch; }
set { ch = value; }
}
RectangleF bounds;
public RectangleF Bounds
{
get { return bounds; }
set { bounds = value; }
}
}
#endregion
}
相关软件
网友评论
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
支持(0) 盖楼(回复)