图片处理
来源:互联网 发布:侵犯网络隐私权的案例 编辑:程序博客网 时间:2024/06/06 01:51
using System;using System.Collections.Generic;using System.Text;using System.Collections;using System.Drawing;using System.Drawing.Imaging;using System.Runtime.InteropServices;namespace GreenLoongDS{ internal class GLUnCodebase { public Bitmap BitmapOri { get; set; } public Bitmap BitmapNew { get; set; } public bool Ready { get; set; } public GLUnCodebase() { Ready = false; } public GLUnCodebase(Bitmap pic) : this() { BitmapNew = BitmapOri = new Bitmap(pic); //转换为Format32bppRgb } /// <summary> /// 得到灰度图像前景背景的临界值 最大类间方差法,yuanbao,2007.08 /// </summary> /// <returns>前景背景的临界值</returns> public int GetDgGrayValue() { int[] pixelNum = new int[256]; //图象直方图,共256个点 int n, n1, n2; int total; //total为总和,累计值 double m1, m2, sum, csum, fmax, sb; //sb为类间方差,fmax存储最大方差值 int k, t, q; int threshValue = 1; // 阈值 //int step = 1; //生成直方图 for (int i = 0; i < BitmapNew.Width; i++) { for (int j = 0; j < BitmapNew.Height; j++) { //返回各个点的颜色,以RGB表示 pixelNum[BitmapNew.GetPixel(i, j).R]++; //相应的直方图加1 } } //直方图平滑化 for (k = 0; k <= 255; k++) { total = 0; for (t = -2; t <= 2; t++) //与附近2个灰度做平滑化,t值应取较小的值 { q = k + t; if (q < 0) //越界处理 q = 0; if (q > 255) q = 255; total = total + pixelNum[q]; //total为总和,累计值 } pixelNum[k] = (int)((float)total / 5.0 + 0.5); //平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值 } //求阈值 sum = csum = 0.0; n = 0; //计算总的图象的点数和质量矩,为后面的计算做准备 for (k = 0; k <= 255; k++) { sum += (double)k * (double)pixelNum[k]; //x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和 n += pixelNum[k]; //n为图象总的点数,归一化后就是累积概率 } fmax = -1.0; //类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行 n1 = 0; for (k = 0; k < 256; k++) //对每个灰度(从0到255)计算一次分割后的类间方差sb { n1 += pixelNum[k]; //n1为在当前阈值遍前景图象的点数 if (n1 == 0) { continue; } //没有分出前景后景 n2 = n - n1; //n2为背景图象的点数 if (n2 == 0) { break; } //n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环 csum += (double)k * pixelNum[k]; //前景的“灰度的值*其点数”的总和 m1 = csum / n1; //m1为前景的平均灰度 m2 = (sum - csum) / n2; //m2为背景的平均灰度 sb = (double)n1 * (double)n2 * (m1 - m2) * (m1 - m2); //sb为类间方差 if (sb > fmax) //如果算出的类间方差大于前一次算出的类间方差 { fmax = sb; //fmax始终为最大类间方差(otsu) threshValue = k; //取最大类间方差时对应的灰度的k就是最佳阈值 } } return threshValue; } /// <summary> /// 得到灰度图像前景背景的临界值 最大类间方差法,yuanbao,2007.08 /// </summary> /// <returns>前景背景的临界值</returns> public int GetDgGrayValue(Bitmap bmp) { int[] pixelNum = new int[256]; //图象直方图,共256个点 int n, n1, n2; int total; //total为总和,累计值 double m1, m2, sum, csum, fmax, sb; //sb为类间方差,fmax存储最大方差值 int k, t, q; int threshValue = 1; // 阈值 //int step = 1; //生成直方图 for (int i = 0; i < bmp.Width; i++) { for (int j = 0; j < bmp.Height; j++) { //返回各个点的颜色,以RGB表示 pixelNum[bmp.GetPixel(i, j).R]++; //相应的直方图加1 } } //直方图平滑化 for (k = 0; k <= 255; k++) { total = 0; for (t = -2; t <= 2; t++) //与附近2个灰度做平滑化,t值应取较小的值 { q = k + t; if (q < 0) //越界处理 q = 0; if (q > 255) q = 255; total = total + pixelNum[q]; //total为总和,累计值 } pixelNum[k] = (int)((float)total / 5.0 + 0.5); //平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值 } //求阈值 sum = csum = 0.0; n = 0; //计算总的图象的点数和质量矩,为后面的计算做准备 for (k = 0; k <= 255; k++) { sum += (double)k * (double)pixelNum[k]; //x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和 n += pixelNum[k]; //n为图象总的点数,归一化后就是累积概率 } fmax = -1.0; //类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行 n1 = 0; for (k = 0; k < 256; k++) //对每个灰度(从0到255)计算一次分割后的类间方差sb { n1 += pixelNum[k]; //n1为在当前阈值遍前景图象的点数 if (n1 == 0) { continue; } //没有分出前景后景 n2 = n - n1; //n2为背景图象的点数 if (n2 == 0) { break; } //n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环 csum += (double)k * pixelNum[k]; //前景的“灰度的值*其点数”的总和 m1 = csum / n1; //m1为前景的平均灰度 m2 = (sum - csum) / n2; //m2为背景的平均灰度 sb = (double)n1 * (double)n2 * (m1 - m2) * (m1 - m2); //sb为类间方差 if (sb > fmax) //如果算出的类间方差大于前一次算出的类间方差 { fmax = sb; //fmax始终为最大类间方差(otsu) threshValue = k; //取最大类间方差时对应的灰度的k就是最佳阈值 } } return threshValue; } /**/ /// <summary> /// 根据RGB,计算灰度值 /// </summary> /// <param name="posClr">Color值</param> /// <returns>灰度值,整型</returns> private int GetGrayNumColor(System.Drawing.Color posClr) { //int i = (int)(0.299 * posClr.R + 0.587 * posClr.G + 0.114 * posClr.B); int i2 = (posClr.R * 19595 + posClr.G * 38469 + posClr.B * 7472) >> 16; return i2; } /// <summary> /// 切掉X左右两边 /// </summary> /// <param name="count"></param> public void CutBorderX(int count) { //x0也是一条边 //也就是说不要忽略边界 CutBorder(count, 0); } /// <summary> /// 切掉Y上下两边 /// </summary> /// <param name="count"></param> public void CutBorderY(int count) { CutBorder(0, count); } /// <summary> /// 切掉XY四边 /// </summary> /// <param name="countX"></param> /// <param name="countY"></param> public void CutBorder(int countX, int countY) { Bitmap bmpNew = new Bitmap(BitmapNew.Width - countX * 2, BitmapNew.Height - 2 * countY); int beginX = countX == 0 ? 0 : countX; int endX = BitmapNew.Width - countX * 2; int beginY = countY == 0 ? 0 : countY; int endY = BitmapNew.Height - countY * 2; for (int x = beginX; x < endX; x++) { for (int y = beginY; y < endY; y++) { bmpNew.SetPixel(x - beginX, y - beginY, BitmapNew.GetPixel(x, y)); } } BitmapNew = bmpNew; } /// <summary> /// 负值削0边,正数削高数边 /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void CutBorderOneSide(int x, int y) { Bitmap bmpNew = new Bitmap(BitmapNew.Width - (x < 0 ? x * -1 : x), BitmapNew.Height - (y < 0 ? y * -1 : y)); for (int _x = 0; _x < bmpNew.Width - 1; _x++) { for (int _y = 0; _y < bmpNew.Height - 1; _y++) { bmpNew.SetPixel(_x, _y, BitmapNew.GetPixel(_x + (x < 0 ? x * -1 : x), _y + (y < 0 ? y * -1 : y))); } } BitmapNew = bmpNew; } /// <summary> /// 在水平方向调整偏移量 /// </summary> /// <param name="count">移动的单位</param> /// <param name="balance">平衡数</param> public void MoveLeft(int count, int balance) { Bitmap bmpNew = new Bitmap(BitmapNew.Width, BitmapNew.Height); int curX = 0; for (int x = BitmapNew.Width - 1; x > 0; x--) { for (int y = BitmapNew.Height - 1; y > 0; y--) { curX = x + (int)((1.5f * y * count) / BitmapNew.Height); //左边移除count个像素列 if (curX < count * 2 + balance || curX > BitmapNew.Width - 1) break; bmpNew.SetPixel(curX, y, BitmapNew.GetPixel(x, y)); } } BitmapNew = bmpNew; CutBorder(count, 0); CutBorderOneSide(count + balance + 1, 0); } public void ViewImage() { for (int x = 0; x < BitmapNew.Width; x++) { for (int y = 0; y < BitmapNew.Height; y++) { Color c = BitmapNew.GetPixel(x, y); } } } /// <summary> /// 利记使用的 /// </summary> public void MoveLeft() { MoveLeft(3, 4); } /// <summary> /// 在分割识别前预处理 /// </summary> public void GetCodeReady() { GrayByPixels(); //灰度处理 GetPicValidByValue(GetDgGrayValue(), 4); //得到有效空间 Ready = true; } /// <summary> /// 在分割识别前预处理 /// </summary> public void GetCodeReady(int grayValue, int codeCount) { GrayByPixels(); //灰度处理 GetPicValidByValue(grayValue, codeCount); //得到有效空间 Ready = true; } /// <summary> /// 转换得到特征码 /// </summary> /// <param name="bmp"></param> /// <returns></returns> public string GetCodeValue(Bitmap bmp) { //GrayByPixels(); //灰度处理 //GetPicValidByValue(128, 4); //得到有效空间 //Bitmap[] pics = GetSplitPics(4, 1); //分割 string code = GetSingleBmpCode(bmp, GetDgGrayValue(bmp)); //得到代码串 return code; } /**/ /// <summary> /// 灰度转换,逐点方式 /// </summary> public void GrayByPixels() { for (int i = 0; i < BitmapNew.Height; i++) { for (int j = 0; j < BitmapNew.Width; j++) { int tmpValue = GetGrayNumColor(BitmapNew.GetPixel(j, i)); BitmapNew.SetPixel(j, i, Color.FromArgb(tmpValue, tmpValue, tmpValue)); } } } /**/ /// <summary> /// 去图形边框,仅做白色处理 /// </summary> /// <param name="borderWidth"></param> public void ClearPicBorder(int borderWidth) { for (int i = 0; i < BitmapNew.Height; i++) { for (int j = 0; j < BitmapNew.Width; j++) { //如果x或y坐标的值小于去边的值 //如果去边的值大于图片的总高或总宽减去去边值加值 if (i < borderWidth || j < borderWidth || j > BitmapNew.Width - 1 - borderWidth || i > BitmapNew.Height - 1 - borderWidth) BitmapNew.SetPixel(j, i, Color.FromArgb(255, 255, 255)); } } } /**/ /// <summary> /// 灰度转换,逐行方式 /// </summary> public void GrayByLine() { Rectangle rec = new Rectangle(0, 0, BitmapNew.Width, BitmapNew.Height); BitmapData bmpData = BitmapNew.LockBits(rec, ImageLockMode.ReadWrite, BitmapNew.PixelFormat);// PixelFormat.Format32bppPArgb); // bmpData.PixelFormat = PixelFormat.Format24bppRgb; IntPtr scan0 = bmpData.Scan0; int len = BitmapNew.Width * BitmapNew.Height; int[] pixels = new int[len]; Marshal.Copy(scan0, pixels, 0, len); //对图片进行处理 int GrayValue = 0; for (int i = 0; i < len; i++) { GrayValue = GetGrayNumColor(Color.FromArgb(pixels[i])); pixels[i] = (byte)(Color.FromArgb(GrayValue, GrayValue, GrayValue)).ToArgb(); //Color转byte } BitmapNew.UnlockBits(bmpData); } /**/ /// <summary> /// 得到有效图形并调整为可平均分割的大小 /// </summary> /// <param name="dgGrayValue">灰度背景分界值</param> /// <param name="CharsCount">有效字符数</param> /// <returns></returns> public void GetPicValidByValue(int dgGrayValue, int CharsCount) { int posx1 = BitmapNew.Width; int posy1 = BitmapNew.Height; int posx2 = 0; int posy2 = 0; for (int y = 0; y < BitmapNew.Height; y++) //找有效区 { for (int x = 0; x < BitmapNew.Width; x++) { int pixelValue = BitmapNew.GetPixel(x, y).R; if (pixelValue < dgGrayValue) //根据灰度值 { if (posx1 > x) posx1 = x; if (posy1 > y) posy1 = y; if (posx2 < x) posx2 = x; if (posy2 < y) posy2 = y; }; }; }; // 确保能整除 int Span = CharsCount - (posx2 - posx1 + 1) % CharsCount; //可整除的差额数 if (Span < CharsCount) { int leftSpan = Span / 2; //分配到左边的空列 ,如span为单数,则右边比左边大1 if (posx1 > leftSpan) posx1 = posx1 - leftSpan; if (posx2 + Span - leftSpan < BitmapNew.Width) posx2 = posx2 + Span - leftSpan; } //复制新图 Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1); BitmapNew = BitmapNew.Clone(cloneRect, BitmapNew.PixelFormat); } /**/ /// <summary> /// 得到有效图形,图形为类变量 /// </summary> /// <param name="dgGrayValue">灰度背景分界值</param> /// <param name="CharsCount">有效字符数</param> /// <returns></returns> public void GetPicValidByValue(int dgGrayValue) { int posx1 = BitmapNew.Width; int posy1 = BitmapNew.Height; int posx2 = 0; int posy2 = 0; for (int i = 0; i < BitmapNew.Height; i++) //找有效区 { for (int j = 0; j < BitmapNew.Width; j++) { int pixelValue = BitmapNew.GetPixel(j, i).R; if (pixelValue < dgGrayValue) //根据灰度值 { if (posx1 > j) posx1 = j; if (posy1 > i) posy1 = i; if (posx2 < j) posx2 = j; if (posy2 < i) posy2 = i; }; }; }; //复制新图 Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1); BitmapNew = BitmapNew.Clone(cloneRect, BitmapNew.PixelFormat); } /**/ /// <summary> /// 得到有效图形,图形由外面传入 /// </summary> /// <param name="dgGrayValue">灰度背景分界值</param> /// <param name="CharsCount">有效字符数</param> /// <returns></returns> public Bitmap GetPicValidByValue(Bitmap singlepic, int dgGrayValue) { int posx1 = singlepic.Width; int posy1 = singlepic.Height; int posx2 = 0; int posy2 = 0; for (int i = 0; i < singlepic.Height; i++) //找有效区 { for (int j = 0; j < singlepic.Width; j++) { int pixelValue = singlepic.GetPixel(j, i).R; if (pixelValue < dgGrayValue) //根据灰度值 { if (posx1 > j) posx1 = j; if (posy1 > i) posy1 = i; if (posx2 < j) posx2 = j; if (posy2 < i) posy2 = i; }; }; }; //复制新图 Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1); return singlepic.Clone(cloneRect, singlepic.PixelFormat); } /**/ /// <summary> /// 平均分割图片 /// </summary> /// <param name="RowNum">水平上分割数</param> /// <param name="ColNum">垂直上分割数</param> /// <returns>分割好的图片数组</returns> public Bitmap[] GetSplitPics(int RowNum, int ColNum) { if (RowNum == 0 || ColNum == 0) return null; int singW = BitmapNew.Width / RowNum; int singH = BitmapNew.Height / ColNum; Bitmap[] PicArray = new Bitmap[RowNum * ColNum]; Rectangle cloneRect; for (int i = 0; i < ColNum; i++) //找有效区 { for (int j = 0; j < RowNum; j++) { cloneRect = new Rectangle(j * singW, i * singH, singW, singH); PicArray[i * RowNum + j] = BitmapNew.Clone(cloneRect, BitmapNew.PixelFormat);//复制小块图 } } return PicArray; } /**/ /// <summary> /// 返回灰度图片的点阵描述字串,1表示灰点,0表示背景 /// </summary> /// <param name="singlepic">灰度图</param> /// <param name="dgGrayValue">背前景灰色界限</param> /// <returns></returns> public string GetSingleBmpCode(Bitmap singlepic, int dgGrayValue) { Color piexl; string code = ""; for (int posy = 0; posy < singlepic.Height; posy++) for (int posx = 0; posx < singlepic.Width; posx++) { piexl = singlepic.GetPixel(posx, posy); if (piexl.R < dgGrayValue) // Color.Black ) code = code + "1"; else code = code + "0"; } return code; } /// <summary> /// 比较匹配度,也就是相同位置的字符相同的总数处于比较字符串最小的长度 /// </summary> /// <param name="m1"></param> /// <param name="m2"></param> /// <returns></returns> protected float compare_parttern(string m1, string m2) { int length = m1.Length; int num2 = m2.Length; int num3 = (length > num2) ? num2 : length;//获得长度最小的数 int num4 = 0; for (int i = 0; i < num3; i++) { if (m2[i] == m1[i]) { num4++; } } return ((1f * num4) / ((float)num3));//匹配数除以比较数 } /// <summary> /// 返回图片验证码字符串 /// </summary> /// <param name="countX">水平切割数</param> /// <param name="countY">上下切割数</param> /// <param name="dic">特征码字典</param> /// <returns></returns> public string GetCodeName(int countX, int countY, Dictionary<string, List<string>> dic) { return GetCodeName(GetSplitPics(countX, countY), dic); } /// <summary> /// 返回图片验证码字符串 /// </summary> /// <param name="dic">特征码字典</param> public string GetCodeName(Bitmap[] splitPics, Dictionary<string, List<string>> dic) { StringBuilder builder = new StringBuilder(); float num2 = -1f; string ch = "0"; int grayValue = GetDgGrayValue(); foreach (Bitmap bitmap in splitPics) { string singleBmpCode = GetSingleBmpCode(bitmap, grayValue); ch = "0"; num2 = -1f;//刚开始,只要大于基准值0.75,就可以过了. foreach (KeyValuePair<string, List<string>> pair in dic) { string key = pair.Key; foreach (string str2 in pair.Value) { // float num3 = compare_parttern(singleBmpCode, str2); if ((num3 >= 0.75f) && (num3 > num2)) { num2 = num3;//如果大于基准值,则把匹配标准提高,逐步提高 ch = key; } //if (num3 == 1f) break; } } builder.Append(ch); } return builder.ToString(); } }}
阅读全文
0 0
- 图片处理
- 处理图片
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 处理图片
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- 图片处理
- spark+pycharm+python(主要介绍pycharm的设置)
- stm32 备份寄存器 读写数据
- Flask与Ajax前后端交互的跨域访问问题
- 171. Excel Sheet Column Number
- poj 3842 An Industrial Spy(dfs+乱搞)
- 图片处理
- 想做iPhoneX抢购活动?压测大师先教你优化网站后台
- 八大排序
- “双向链表的一些基本操作”
- 进程与线程---Python_Daily
- OpenCV摄像头获取视频并实时保存每帧图片
- poj1573(模拟)
- Python机器学习——Agglomerative层次聚类
- 【PAT】【Advanced Level】1130. Infix Expression (25)