110,539
社区成员
发帖
与我相关
我的任务
分享
rect.Width += 1; rect.Height += 1;
if (nCount < nPixelMin || nCount > nPixelMax) {
foreach (var v in lstTemp) {
this.SetColorFormByColorInfo(v.X, v.Y, Color.White);
}
return Rectangle.Empty;
}
看到上面的图 为什么没有圈出来的地方是白色的 我就觉得奇怪了 然后我刚才突然发现 为什么 里面会有这个循环 这不是脑残了吗 多次一句不说 还浪费时间 浪费的不只是一个循环的时间 由于被设置成了白色 下次遍历到的时候 遇到白色 又会去判断一次 因为我是一行一行遍历的 遇到一个白色 就去找和这个白色连通的像素点 这代码删掉吧
把那个循环注释掉后 我电脑20毫秒左右出结果 不注释 接近200毫秒 我就不知道 当时写代码时候 脑子是不是短路了。。。
private void button1_Click(object sender, EventArgs e) {
Image img = Image.FromFile("./fuck.png");
List<Rectangle> lstRect = this.GetCharRect(img, 0, int.MaxValue);
using (Graphics g = this.CreateGraphics()) {
g.DrawImage(img, 0, 0);
lstRect.ForEach(r => {
g.DrawRectangle(Pens.Cyan, r);
});
}
}
private BitmapData m_bmpData;
private byte[] m_byColorInfo;
/// <summary>
/// 获取验证码字符所在的区域
/// </summary>
/// <param name="imgDark">二值化后的图像</param>
/// <param name="nPixelMin">连续的最小像素个数 小于此数将被忽略</param>
/// <param name="nPixelMax">连续的最大像素个数 大于此数将被忽略</param>
/// <returns></returns>
public List<Rectangle> GetCharRect(Image imgDark, int nPixelMin, int nPixelMax) {
Bitmap bmp = (Bitmap)imgDark;
m_bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
m_byColorInfo = new byte[bmp.Height * m_bmpData.Stride];
Marshal.Copy(m_bmpData.Scan0, m_byColorInfo, 0, m_byColorInfo.Length);
List<Rectangle> lstRect = new List<Rectangle>();
for (int y = 0, leny = bmp.Height; y < leny; y++) {
for (int x = 0, lenx = bmp.Width; x < lenx; x++) {
if (this.GetArgbFormByColor(x, y) == Color.White.ToArgb()) {//【【【注意 你需要的是白色】】】
Rectangle rectTemp = this.GetRectFromPoint(nPixelMin, nPixelMax, new Point(x, y), Color.White, Color.Magenta);
if (rectTemp != Rectangle.Empty) lstRect.Add(rectTemp);
}
}
}
Marshal.Copy(m_byColorInfo, 0, m_bmpData.Scan0, m_byColorInfo.Length);
bmp.UnlockBits(m_bmpData);
//将区域按照left属性排序
for (int i = 0; i < lstRect.Count; i++) {
for (int j = 1; j < lstRect.Count - i; j++) {
if (lstRect[j - 1].Left > lstRect[j].Left) {
Rectangle rectTemp = lstRect[j];
lstRect[j] = lstRect[j - 1];
lstRect[j - 1] = rectTemp;
}
}
}
return lstRect;
}
private Rectangle GetRectFromPoint(int nPixelMin, int nPixelMax, Point ptStart, Color clrSrc, Color clrSet) {
int nCount = 0;
int nArgb = clrSrc.ToArgb();
Rectangle rect = new Rectangle(ptStart.X, ptStart.Y, 0, 0);
List<Point> ptRegList = new List<Point>();
List<Point> lstTemp = new List<Point>();
ptRegList.Add(ptStart);
lstTemp.Add(ptStart);
this.SetColorFormByColorInfo(ptStart.X, ptStart.Y, clrSet);
while (ptRegList.Count != 0) {
Point ptTemp = this.GetNextPoint(ptRegList[ptRegList.Count - 1], nArgb);
//Point ptTemp = ptRegList[ptRegList.Count - 1];
if (ptTemp != Point.Empty) {
ptRegList.Add(ptTemp);
lstTemp.Add(ptTemp);
this.SetColorFormByColorInfo(ptTemp.X, ptTemp.Y, clrSet);
nCount++;
if (ptTemp.X < rect.Left) { rect.Width = rect.Right - ptTemp.X; rect.X = ptTemp.X; }
if (ptTemp.Y < rect.Top) { rect.Height = rect.Bottom - ptTemp.Y; rect.Y = ptTemp.Y; }
if (ptTemp.X > rect.Right) rect.Width = ptTemp.X - rect.Left;
if (ptTemp.Y > rect.Bottom) rect.Height = ptTemp.Y - rect.Top;
} else
ptRegList.RemoveAt(ptRegList.Count - 1);
}
rect.Width += 1; rect.Height += 1;
if (nCount < nPixelMin || nCount > nPixelMax) {
foreach (var v in lstTemp) {
this.SetColorFormByColorInfo(v.X, v.Y, Color.White);
}
return Rectangle.Empty;
}
return rect;
}
private Point GetNextPoint(Point ptStart, int nArgb) {
if (m_bmpData.Height > ptStart.Y + 1 && this.GetArgbFormByColor(ptStart.X, ptStart.Y + 1) == nArgb)
return new Point(ptStart.X, ptStart.Y + 1);
if (m_bmpData.Width > ptStart.X + 1 && this.GetArgbFormByColor(ptStart.X + 1, ptStart.Y) == nArgb)
return new Point(ptStart.X + 1, ptStart.Y);
if (0 <= ptStart.Y - 1 && this.GetArgbFormByColor(ptStart.X, ptStart.Y - 1) == nArgb)
return new Point(ptStart.X, ptStart.Y - 1);
if (0 <= ptStart.X - 1 && this.GetArgbFormByColor(ptStart.X - 1, ptStart.Y) == nArgb)
return new Point(ptStart.X - 1, ptStart.Y);
if (0 <= ptStart.X - 1 && m_bmpData.Height > ptStart.Y + 1 && this.GetArgbFormByColor(ptStart.X - 1, ptStart.Y + 1) == nArgb)
return new Point(ptStart.X - 1, ptStart.Y + 1);
if (m_bmpData.Width > ptStart.X + 1 && m_bmpData.Height > ptStart.Y + 1 && this.GetArgbFormByColor(ptStart.X + 1, ptStart.Y + 1) == nArgb)
return new Point(ptStart.X + 1, ptStart.Y + 1);
if (m_bmpData.Width > ptStart.X + 1 && 0 <= ptStart.Y - 1 && this.GetArgbFormByColor(ptStart.X + 1, ptStart.Y - 1) == nArgb)
return new Point(ptStart.X + 1, ptStart.Y - 1);
if (0 <= ptStart.X - 1 && 0 <= ptStart.Y - 1 && this.GetArgbFormByColor(ptStart.X - 1, ptStart.Y - 1) == nArgb)
return new Point(ptStart.X - 1, ptStart.Y - 1);
return Point.Empty;
}
private int GetArgbFormByColor(int x, int y) {
return Color.FromArgb(255,
m_byColorInfo[y * m_bmpData.Stride + x * 3],
m_byColorInfo[y * m_bmpData.Stride + x * 3 + 1],
m_byColorInfo[y * m_bmpData.Stride + x * 3 + 2]).ToArgb();
}
private void SetColorFormByColorInfo(int x, int y, Color clr) {
m_byColorInfo[y * m_bmpData.Stride + x * 3] = clr.B;
m_byColorInfo[y * m_bmpData.Stride + x * 3 + 1] = clr.G;
m_byColorInfo[y * m_bmpData.Stride + x * 3 + 2] = clr.R;
}