------- jeff377--------------------------------------------
我研究所的论文就是在做类神经网络处理文字辨识,以你的例子而言,旋转随意角度对辨识来说并不会有太大影响,只要抓字的重心,360度旋转抓取特微值,还是可以辨识的出来。
通常文字辨识的有一个重要的动作,就是要把个别文字分割,你只要把文字弄的难分割就有不错的安全性。
---------------------------------------------------
代码比较粗糙,而且比较菜,其中遇到一个问题, 未对 Graphics 填充底色,那么文字的 ClearType 效果没有了,文字毛边比较明显,不知道为什么,谁能告诉竹子?
代码相对粗糙,没有考虑更多的情况,在测试过程中,以20px 字体呈现,效果感觉还不错,只是 ClearType 效果没有了。
帖几张看看
------------
------------
------------
------------
有一些随机的不好,象下面这张
相关链接:
查看 V1.0
.NET 2.0 代码如下:
using
System;
using System.Drawing;
using System.Web;
namespace Oran.Image
{
/// <summary>
/// 旋转的可视验证码图象
/// </summary>
public class RotatedVlidationCode
{
public enum RandomStringMode
{
/// <summary>
/// 小写字母
/// </summary>
LowerLetter,
/// <summary>
/// 大写字母
/// </summary>
UpperLetter,
/// <summary>
/// 混合大小写字母
/// </summary>
Letter,
/// <summary>
/// 数字
/// </summary>
Digital,
/// <summary>
/// 混合数字与大小字母
/// </summary>
Mix
}
public static string GenerateRandomString( int length, RandomStringMode mode)
{
string rndStr = string .Empty;
if (length == 0 )
return rndStr;
// 以数组方式候选字符,可以更方便的剔除不要的字符,如数字 0 与字母 o
char [] digitals = new char [ 10 ] { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' };
char [] lowerLetters = new char [ 26 ] {
' a ' , ' b ' , ' c ' , ' d ' , ' e ' , ' f ' , ' g ' ,
' h ' , ' i ' , ' j ' , ' k ' , ' l ' , ' m ' , ' n ' ,
' o ' , ' p ' , ' q ' , ' r ' , ' s ' , ' t ' ,
' u ' , ' v ' , ' w ' , ' x ' , ' y ' , ' z ' };
char [] upperLetters = new char [ 26 ] {
' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' , ' G ' ,
' H ' , ' I ' , ' J ' , ' K ' , ' L ' , ' M ' , ' N ' ,
' O ' , ' P ' , ' Q ' , ' R ' , ' S ' , ' T ' ,
' U ' , ' V ' , ' W ' , ' X ' , ' Y ' , ' Z ' };
char [] letters = new char [ 52 ]{
' a ' , ' b ' , ' c ' , ' d ' , ' e ' , ' f ' , ' g ' ,
' h ' , ' i ' , ' j ' , ' k ' , ' l ' , ' m ' , ' n ' ,
' o ' , ' p ' , ' q ' , ' r ' , ' s ' , ' t ' ,
' u ' , ' v ' , ' w ' , ' x ' , ' y ' , ' z ' ,
' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' , ' G ' ,
' H ' , ' I ' , ' J ' , ' K ' , ' L ' , ' M ' , ' N ' ,
' O ' , ' P ' , ' Q ' , ' R ' , ' S ' , ' T ' ,
' U ' , ' V ' , ' W ' , ' X ' , ' Y ' , ' Z ' };
char [] mix = new char [ 62 ]{
' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' ,
' a ' , ' b ' , ' c ' , ' d ' , ' e ' , ' f ' , ' g ' ,
' h ' , ' i ' , ' j ' , ' k ' , ' l ' , ' m ' , ' n ' ,
' o ' , ' p ' , ' q ' , ' r ' , ' s ' , ' t ' ,
' u ' , ' v ' , ' w ' , ' x ' , ' y ' , ' z ' ,
' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' , ' G ' ,
' H ' , ' I ' , ' J ' , ' K ' , ' L ' , ' M ' , ' N ' ,
' O ' , ' P ' , ' Q ' , ' R ' , ' S ' , ' T ' ,
' U ' , ' V ' , ' W ' , ' X ' , ' Y ' , ' Z ' };
int [] range = new int [ 2 ] { 0 , 0 };
Random random = new Random();
switch (mode)
{
case RandomStringMode.Digital:
for ( int i = 0 ; i < length; ++ i)
rndStr += digitals[random.Next( 0 , digitals.Length)];
break ;
case RandomStringMode.LowerLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += lowerLetters[random.Next( 0 , lowerLetters.Length)];
break ;
case RandomStringMode.UpperLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += upperLetters[random.Next( 0 , upperLetters.Length)];
break ;
case RandomStringMode.Letter:
for ( int i = 0 ; i < length; ++ i)
rndStr += letters[random.Next( 0 , letters.Length)];
break ;
default :
for ( int i = 0 ; i < length; ++ i)
rndStr += mix[random.Next( 0 , mix.Length)];
break ;
}
return rndStr;
}
/// <summary>
/// 显示验证码
/// </summary>
/// <param name="seed"> 随机数辅助种子 </param>
/// <param name="strLen"> 验证码字符长度 </param>
/// <param name="fontSize"> 字体大小 </param>
/// <param name="mode"> 随机字符模式 </param>
/// <param name="clrFont"> 字体颜色 </param>
/// <param name="clrBg"> 背景颜色 </param>
public static void ShowValidationCode( ref int seed, int strLen, int fontSize, RandomStringMode mode, Color clrFont, Color clrBg)
{
int tmpSeed;
unchecked
{
tmpSeed = ( int )(seed * DateTime.Now.Ticks);
++ seed;
}
Random rnd = new Random(tmpSeed);
string text = GenerateRandomString(strLen, mode);
int height = fontSize * 2 ;
// 因为字体旋转后每个字体所占宽度会所有加大,所以要加一点补偿宽度
int width = fontSize * text.Length + fontSize / (text.Length - 2 );
Bitmap bmp = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bmp);
Font font = new Font( " Courier New " , fontSize, FontStyle.Bold);
Brush brush = new SolidBrush(clrFont);
Brush brushBg = new SolidBrush(clrBg);
graphics.FillRectangle(brushBg, 0 , 0 , width, height);
Bitmap tmpBmp = new Bitmap(height, height);
Graphics tmpGph = null ;
int degree = 40 ;
Point tmpPoint = new Point();
for ( int i = 0 ; i < text.Length; i ++ )
{
tmpBmp = new Bitmap(height, height);
tmpGph = Graphics.FromImage(tmpBmp);
// tmpGph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
// 不填充底色,文字 ClearType 效果不见了,why?!
// tmpGph.FillRectangle(brushBg, 0, 0, tmpBmp.Width, tmpBmp.Height);
degree = rnd.Next( 20 , 51 ); // [20, 50]随机角度
if (rnd.Next( 0 , 2 ) == 0 )
{
tmpPoint.X = 12 ; // 调整文本坐标以适应旋转后的图象
tmpPoint.Y = - 6 ;
}
else
{
degree = ~ degree + 1 ; // 逆时针旋转
tmpPoint.X = - 10 ;
tmpPoint.Y = 6 ;
}
tmpGph.RotateTransform(degree);
tmpGph.DrawString(text[i].ToString(), font, brush, tmpPoint);
graphics.DrawImage(tmpBmp, i * fontSize, 0 ); // 拼接图象
}
// 输出图象
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ContentType = " image/gif " ;
HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray());
HttpContext.Current.Response.End();
// 释放资源
font.Dispose();
brush.Dispose();
brushBg.Dispose();
tmpGph.Dispose();
tmpBmp.Dispose();
graphics.Dispose();
bmp.Dispose();
memoryStream.Dispose();
}
}
}
using System.Drawing;
using System.Web;
namespace Oran.Image
{
/// <summary>
/// 旋转的可视验证码图象
/// </summary>
public class RotatedVlidationCode
{
public enum RandomStringMode
{
/// <summary>
/// 小写字母
/// </summary>
LowerLetter,
/// <summary>
/// 大写字母
/// </summary>
UpperLetter,
/// <summary>
/// 混合大小写字母
/// </summary>
Letter,
/// <summary>
/// 数字
/// </summary>
Digital,
/// <summary>
/// 混合数字与大小字母
/// </summary>
Mix
}
public static string GenerateRandomString( int length, RandomStringMode mode)
{
string rndStr = string .Empty;
if (length == 0 )
return rndStr;
// 以数组方式候选字符,可以更方便的剔除不要的字符,如数字 0 与字母 o
char [] digitals = new char [ 10 ] { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' };
char [] lowerLetters = new char [ 26 ] {
' a ' , ' b ' , ' c ' , ' d ' , ' e ' , ' f ' , ' g ' ,
' h ' , ' i ' , ' j ' , ' k ' , ' l ' , ' m ' , ' n ' ,
' o ' , ' p ' , ' q ' , ' r ' , ' s ' , ' t ' ,
' u ' , ' v ' , ' w ' , ' x ' , ' y ' , ' z ' };
char [] upperLetters = new char [ 26 ] {
' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' , ' G ' ,
' H ' , ' I ' , ' J ' , ' K ' , ' L ' , ' M ' , ' N ' ,
' O ' , ' P ' , ' Q ' , ' R ' , ' S ' , ' T ' ,
' U ' , ' V ' , ' W ' , ' X ' , ' Y ' , ' Z ' };
char [] letters = new char [ 52 ]{
' a ' , ' b ' , ' c ' , ' d ' , ' e ' , ' f ' , ' g ' ,
' h ' , ' i ' , ' j ' , ' k ' , ' l ' , ' m ' , ' n ' ,
' o ' , ' p ' , ' q ' , ' r ' , ' s ' , ' t ' ,
' u ' , ' v ' , ' w ' , ' x ' , ' y ' , ' z ' ,
' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' , ' G ' ,
' H ' , ' I ' , ' J ' , ' K ' , ' L ' , ' M ' , ' N ' ,
' O ' , ' P ' , ' Q ' , ' R ' , ' S ' , ' T ' ,
' U ' , ' V ' , ' W ' , ' X ' , ' Y ' , ' Z ' };
char [] mix = new char [ 62 ]{
' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' ,
' a ' , ' b ' , ' c ' , ' d ' , ' e ' , ' f ' , ' g ' ,
' h ' , ' i ' , ' j ' , ' k ' , ' l ' , ' m ' , ' n ' ,
' o ' , ' p ' , ' q ' , ' r ' , ' s ' , ' t ' ,
' u ' , ' v ' , ' w ' , ' x ' , ' y ' , ' z ' ,
' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' , ' G ' ,
' H ' , ' I ' , ' J ' , ' K ' , ' L ' , ' M ' , ' N ' ,
' O ' , ' P ' , ' Q ' , ' R ' , ' S ' , ' T ' ,
' U ' , ' V ' , ' W ' , ' X ' , ' Y ' , ' Z ' };
int [] range = new int [ 2 ] { 0 , 0 };
Random random = new Random();
switch (mode)
{
case RandomStringMode.Digital:
for ( int i = 0 ; i < length; ++ i)
rndStr += digitals[random.Next( 0 , digitals.Length)];
break ;
case RandomStringMode.LowerLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += lowerLetters[random.Next( 0 , lowerLetters.Length)];
break ;
case RandomStringMode.UpperLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += upperLetters[random.Next( 0 , upperLetters.Length)];
break ;
case RandomStringMode.Letter:
for ( int i = 0 ; i < length; ++ i)
rndStr += letters[random.Next( 0 , letters.Length)];
break ;
default :
for ( int i = 0 ; i < length; ++ i)
rndStr += mix[random.Next( 0 , mix.Length)];
break ;
}
return rndStr;
}
/// <summary>
/// 显示验证码
/// </summary>
/// <param name="seed"> 随机数辅助种子 </param>
/// <param name="strLen"> 验证码字符长度 </param>
/// <param name="fontSize"> 字体大小 </param>
/// <param name="mode"> 随机字符模式 </param>
/// <param name="clrFont"> 字体颜色 </param>
/// <param name="clrBg"> 背景颜色 </param>
public static void ShowValidationCode( ref int seed, int strLen, int fontSize, RandomStringMode mode, Color clrFont, Color clrBg)
{
int tmpSeed;
unchecked
{
tmpSeed = ( int )(seed * DateTime.Now.Ticks);
++ seed;
}
Random rnd = new Random(tmpSeed);
string text = GenerateRandomString(strLen, mode);
int height = fontSize * 2 ;
// 因为字体旋转后每个字体所占宽度会所有加大,所以要加一点补偿宽度
int width = fontSize * text.Length + fontSize / (text.Length - 2 );
Bitmap bmp = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bmp);
Font font = new Font( " Courier New " , fontSize, FontStyle.Bold);
Brush brush = new SolidBrush(clrFont);
Brush brushBg = new SolidBrush(clrBg);
graphics.FillRectangle(brushBg, 0 , 0 , width, height);
Bitmap tmpBmp = new Bitmap(height, height);
Graphics tmpGph = null ;
int degree = 40 ;
Point tmpPoint = new Point();
for ( int i = 0 ; i < text.Length; i ++ )
{
tmpBmp = new Bitmap(height, height);
tmpGph = Graphics.FromImage(tmpBmp);
// tmpGph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
// 不填充底色,文字 ClearType 效果不见了,why?!
// tmpGph.FillRectangle(brushBg, 0, 0, tmpBmp.Width, tmpBmp.Height);
degree = rnd.Next( 20 , 51 ); // [20, 50]随机角度
if (rnd.Next( 0 , 2 ) == 0 )
{
tmpPoint.X = 12 ; // 调整文本坐标以适应旋转后的图象
tmpPoint.Y = - 6 ;
}
else
{
degree = ~ degree + 1 ; // 逆时针旋转
tmpPoint.X = - 10 ;
tmpPoint.Y = 6 ;
}
tmpGph.RotateTransform(degree);
tmpGph.DrawString(text[i].ToString(), font, brush, tmpPoint);
graphics.DrawImage(tmpBmp, i * fontSize, 0 ); // 拼接图象
}
// 输出图象
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ContentType = " image/gif " ;
HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray());
HttpContext.Current.Response.End();
// 释放资源
font.Dispose();
brush.Dispose();
brushBg.Dispose();
tmpGph.Dispose();
tmpBmp.Dispose();
graphics.Dispose();
bmp.Dispose();
memoryStream.Dispose();
}
}
}