/// <summary> /// 二值化最——大类间方差法 /// </summary> /// <returns>返回计算的阈值</returns> public static int BinaryImg(PICLib.GrayImg inBase, out PICLib.GrayImg outBase) { int w = inBase.Width; int h = inBase.Height; int[] range = new int[256]; for (int i = 0; i < 256; i++) range[i] = 0; for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) if (j > 5 && j < h - 5 && i > 5 && i < w - 5) range[inBase.Img[i + j * w]]++; } int a = w * h; int lowerQuart = 0; for (int i = 0; (double)i < (double)a * 0.01D; ) { i += range[lowerQuart]; lowerQuart++; } int thresh = (byte)(lowerQuart + 10); BinaryImg(inBase, out outBase, (byte)thresh); return thresh; }
/// <summary> /// 图像二值化——普通 /// </summary> /// <param name="inBase"></param> /// <param name="outBase"></param> /// <param name="threshold"></param> public static void BinaryImg(PICLib.GrayImg inBase, out PICLib.GrayImg outBase, int threshold) { byte Max = 255, Min = 0; int Allpixel = inBase.Width * inBase.Height; PICLib.PicBase.ImgMalloc(out outBase, inBase.Width, inBase.Height); for (int i = 0; i < Allpixel; i++) outBase.Img[i] = inBase.Img[i] > threshold ? Max : Min; }
/// <summary> /// 虹膜展开 /// </summary> /// <param name="inBase"></param> /// <param name="outBase"></param> /// <param name="pupil"></param> /// <param name="iris"></param> /// <param name="unrollx"></param> /// <param name="unrolly"></param> public void IrisRoll(PICLib.GrayImg inBase, out PICLib.GrayImg outBase, Circle pupil, Circle iris, int unrollx, int unrolly) { int pcx = pupil.x0; int pcy = pupil.y0; int pr = pupil.radius; int icx = iris.x0; int icy = iris.y0; int ir = iris.radius; int rad = (int)Math.Round((float)((double)ir - Math.Sqrt((pcx - icx) * (pcx - icx) + (pcy - icy) * (pcy - icy)))); int iw = inBase.Width; int ih = inBase.Height; PicBase.ImgMalloc(out outBase, unrollx, unrolly); for (int ww = 0; ww < unrollx; ww++) { for (int wh = 0; wh < unrolly; wh++) { int irisx = (int)Math.Round((float)((double)(float)pcx + Math.Sin((double)((float)ww / (float)unrollx) * 6.2831853071795862D) * (double)((float)pr + ((float)wh / (float)unrolly) * ((float)rad - (float)pr)))); int irisy = (int)Math.Round((float)((double)(float)pcy + Math.Cos((double)((float)ww / (float)unrollx) * 6.2831853071795862D) * (double)((float)pr + ((float)wh / (float)unrolly) * ((float)rad - (float)pr)))); outBase.Img[ww + wh * unrollx] = inBase.Img[irisx + irisy * iw]; } } }
/// <summary> /// 加载图像至右侧区域(有底部说明文字) /// </summary> /// <param name="Pic">传入图像</param> /// <param name="txt">说明文字</param> private void LoadPicOnRight(PICLib.ColorImg Pic, string txt) { DrawPic Temp = new DrawPic(); if ((Pic.Width < 320 && Pic.Height < 240) || (Pic.Width < 240 && Pic.Height < 320)) { Temp.pictureBox1.Width = Pic.Width; Temp.pictureBox1.Height = Pic.Height; Temp.Height = Pic.Height + 12; Temp.Width = Pic.Width; } else if (Pic.Height < Pic.Width) { Temp.Width = 320; Temp.Height = 252; Temp.pictureBox1.Width = 320; Temp.pictureBox1.Height = 240; } else { Temp.Width = 240; Temp.Height = 332; Temp.pictureBox1.Width = 240; Temp.pictureBox1.Height = 320; } Bitmap tmp; PICLib.PicBase.ArrayToImg(out tmp, Pic); //显示图像 Temp.pictureBox1.Image = tmp; //底部文字说明 Temp.TxtShow.Text = txt; flowLayoutOnRight.Controls.Add(Temp); }
/// <summary> /// 加载图像至左侧区域(有底部说明文字) /// </summary> /// <param name="Pic">传入图像</param> /// <param name="txt">说明文字</param> private void LoadPicOnLeft(PICLib.GrayImg Pic, string txt) { DrawPic Temp = new DrawPic(); if ((Pic.Width < 200 && Pic.Height < 150) || (Pic.Width < 150 && Pic.Height < 200)) { Temp.pictureBox1.Width = Pic.Width; Temp.pictureBox1.Height = Pic.Height; Temp.Height = Pic.Height + 12; Temp.Width = Pic.Width; } else if (Pic.Height < Pic.Width) { Temp.Width = 200; Temp.Height = 162; Temp.pictureBox1.Width = 200; Temp.pictureBox1.Height = 150; } else { Temp.Width = 150; Temp.Height = 212; Temp.pictureBox1.Width = 150; Temp.pictureBox1.Height = 200; } Bitmap tmp; PICLib.PicBase.ArrayToImg(out tmp, Pic); //显示图像 Temp.pictureBox1.Image = tmp; Temp.pictureBox1.MouseDoubleClick += new MouseEventHandler(SelectPic); //底部文字说明 Temp.TxtShow.Text = txt; flowLayoutOnLeft.Controls.Add(Temp); }
/// <summary> /// 获取子图 /// </summary> /// <param name="pDestImg">目标图像</param> /// <param name="pSrcImg">源图像</param> /// <param name="rect">截取区域</param> /// <returns></returns> public static int GetSubImg(out PICLib.GrayImg pDestImg, GrayImg pSrcImg, Rectangle rect) { PicBase.ImgMalloc(out pDestImg, rect.Width, rect.Height); for (int y = rect.Top; y < rect.Top + rect.Height; y++) { for (int x = rect.Left; x < rect.Left + rect.Width; x++) { pDestImg.Img[(y - rect.Top) * rect.Width + (x - rect.Left)] = pSrcImg.Img[y * pSrcImg.Width + x]; } } return 1; }
/// <summary> /// 高斯平滑 /// </summary> /// <param name="inBase"></param> /// <param name="outBase"></param> /// <param name="size"></param> /// <param name="variance"></param> public static void GaussianSmooth(PICLib.GrayImg inBase, out PICLib.GrayImg outBase, int size, double variance) { float[] mask = new float[size * size]; int k = 0; float sum = 0.0F; int so2 = (size + 1) / 2; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { k = i + j * size; float xsqr = (i - so2) * (i - so2); float ysqr = (j - so2) * (j - so2); float vsqr = (float)(variance * variance); mask[k] = (float)Math.Exp(-(xsqr + ysqr) / (2.0F * vsqr)); sum += mask[k]; } } for (int i = 0; i < size * size; i++) mask[i] = mask[i] / sum; int width = inBase.Width; int height = inBase.Height; PICLib.PicBase.ImgMalloc(out outBase, width, height); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { sum = 0.0F; if (i - size / 2 < 0 || j - size / 2 < 0 || i + size / 2 >= width || j + size / 2 >= height) { outBase.Img[i + j * width] = 0; } else { int m = 0; for (k = 0 - size / 2; k <= size / 2; k++) { for (int l = 0 - size / 2; l <= size / 2; l++) sum += (float)inBase.Img[i + k + (j + l) * width] * mask[m++]; } outBase.Img[i + j * width] = (byte)sum; } } } }
/// <summary> /// 腐蚀运算,针对目标点为黑色点进行操作 /// </summary> /// <param name="inBase"></param> /// <param name="outBase"></param> /// <param name="Template"></param> /// <param name="TempSize"></param> public static void Erosion(PICLib.GrayImg inBase, out GrayImg outBase, int[] Template, int TempSize) { int w = inBase.Width; int h = inBase.Height; PicBase.ImgMalloc(out outBase, w, h); //ImgClone(out outBase, inBase); int half = (int)Math.Floor((double)TempSize / 2D); for (int ww = half; ww < w - half; ww++) { for (int wh = half; wh < h - half; wh++) { int sw = 0; outBase.Img[ww + wh * w] = 255; for (int ww2 = ww - half; ww2 <= ww + half; ww2++) { int sh = 0; for (int wh2 = wh - half; wh2 <= wh + half; wh2++) { if (!(Template[sw + sh * TempSize] == 1 && inBase.Img[ww2 + wh2 * w] == 255)) { outBase.Img[ww + wh * w] = 0; ww2 = ww + half + 1; wh2 = wh + half + 1; } sh++; } sw++; } } } }
/// <summary> /// 闭运算 /// </summary> /// <param name="inBase"></param> /// <param name="outBase"></param> /// <param name="Template"></param> /// <param name="TempSize"></param> public static void Closing(PICLib.GrayImg inBase, out PICLib.GrayImg outBase, int[] Template, int TempSize) { Dilation(inBase, out outBase, Template, TempSize); Erosion(outBase, out outBase, Template, TempSize); }
/// <summary> /// 开运算 /// </summary> /// <param name="inBase"></param> /// <param name="outBase"></param> /// <param name="Template"></param> /// <param name="TempSize"></param> public void Opening(PICLib.GrayImg inBase, out PICLib.GrayImg outBase, int[] Template, int TempSize) { Erosion(inBase, out outBase, Template, TempSize); Dilation(outBase, out outBase, Template, TempSize); }
Circle findPupil(PICLib.GrayImg inBase, int size, double sigma) { //GreyImage im = RandomImageProcessing.greyscale(image); //RandomImageProcessing.gaussianSmooth(im, size, sigma); //RandomImageProcessing.threshold(im); //im.image = RandomImageProcessing.toBufferedImage(im); Process.GaussianSmooth(inBase, out inBase, size, sigma); Process.BinaryImg(inBase, out inBase); int[] Template = new int[25]; for (int i = 0; i < 25; i++) Template[i] = 1; PICLib.GrayImg OpenedBase; DipTool.Opening(inBase, out OpenedBase, Template, 5); ConnectedRegions regions = DipTool.getConnectedRegions(OpenedBase, inBase.Width, inBase.Height); Circle c = new Circle(); int maxRadius = (int)((regions.maxRect.Width * 1.2D) / 2D); int maxDif = -1; int minRadius = (int)((regions.maxRect.Width * 0.5D) / 2D); int maxX = 0; int maxY = 0; int maxR = 5; int prevX = 0; int prevY = 0; int prevR = 5; int halfSize = (int)(Math.Floor((double)(float)size / 2D) <= (double)minRadius ? minRadius : Math.Floor((double)(float)size / 2D)); int validCount = 0; int invalidCount = 0; for (int x = halfSize; x < inBase.Width - halfSize; x++) { for (int y = halfSize; y < inBase.Height - halfSize; y++) { if (regions.connected[x + y * inBase.Width] == 0) { invalidCount++; } else { int prevSum = -1; for (int radius = minRadius; radius < maxRadius; radius++) { if (x - radius < halfSize || x + radius > inBase.Width - halfSize || y - radius < halfSize || y + radius > inBase.Height - halfSize) break; c.x0 = x; c.y0 = y; c.radius = radius; int radSum = sumCircle(inBase, c, 1.0471975511965976D); if (prevSum != -1 && Math.Abs(prevSum - radSum) > maxDif) { maxDif = Math.Abs(prevSum - radSum); maxX = prevX; maxY = prevY; maxR = prevR; } prevSum = radSum; prevX = x; prevY = y; prevR = radius; } validCount++; } } } c.radius = maxR; c.x0 = maxX; c.y0 = maxY; return c; }
Circle findLimbus(PICLib.GrayImg inBase, Circle pupil, int size, double sigma) { //DipTool.GaussianSmooth(inBase, out inBase, size, sigma); Process.GaussianSmooth(inBase, out inBase, size, sigma); int maxRadius = inBase.Width <= inBase.Height ? inBase.Width : inBase.Height; int maxDif = -1; int minRadius = 30; int maxX = 0; int maxY = 0; int maxR = 5; int prevX = 0; int prevY = 0; int prevR = 5; int halfSize = pupil.radius / 5; Circle c = new Circle(); for (int x = pupil.x0 - halfSize; x < pupil.x0 + halfSize; x++) { for (int y = pupil.y0 - halfSize; y < pupil.y0 + halfSize; y++) if (Math.Sqrt(Math.Pow(x - pupil.x0, 2D) + Math.Pow(y - pupil.y0, 2D)) < (double)pupil.radius) { int prevSum = -1; for (int radius = (int)((double)pupil.radius + Math.Sqrt(Math.Pow(x - pupil.x0, 2D) + Math.Pow(y - pupil.y0, 2D)) + (double)(float)pupil.radius / 2D); radius < maxRadius; radius++) { if (x - radius < size || x + radius > inBase.Width - size || y - radius < 0 || y + radius > inBase.Height) break; c.x0 = x; c.y0 = y; c.radius = radius; int radSum = sumCircle(inBase, c, 0.78539816339744828D); if (prevSum != -1 && Math.Abs(prevSum - radSum) > maxDif) { maxDif = Math.Abs(prevSum - radSum); maxX = prevX; maxY = prevY; maxR = prevR; } prevSum = radSum; prevX = x; prevY = y; prevR = radius; } } } c.x0 = maxX; c.y0 = maxY; c.radius = maxR; return c; }
public int sumCircle(PICLib.GrayImg inBase, Circle c, double cone) { int w = inBase.Width; int h = inBase.Height; double inc = 0.078539816339744828D; int count = (int)((cone * 4D) / inc) + 1; if (storedCos == null || storedCos.Length != count) { storedCos = new double?[count]; storedSin = new double?[count]; } int radSum = 0; int i = 0; for (double angle = Math.PI; angle > 0.0D; angle -= inc) if (angle <= cone || angle >= Math.PI - cone && angle <= Math.PI + cone || angle >= 2 * Math.PI - cone) { double? cosAngle = 0; if ((cosAngle = storedCos[i]) == null) storedCos[i] = cosAngle = Math.Cos(angle); double? sinAngle = 0; if ((sinAngle = storedSin[i]) == null) storedSin[i] = sinAngle = Math.Sin(angle); i++; double floatX = (double)c.radius * (double)cosAngle; double floatY = (double)c.radius * (double)sinAngle; int circX = (int)Math.Round(floatX); if (c.x0 + circX >= 0 && c.x0 + circX < w && c.x0 - circX >= 0 && c.x0 - circX < w) { int circY = (int)Math.Round(floatY); if (c.y0 + circY >= 0 && c.y0 + circY < h && c.y0 - circY >= 0 && c.y0 - circY < h) { radSum += inBase.Img[c.x0 + circX + (c.y0 + circY) * w]; radSum += inBase.Img[(c.x0 - circX) + (c.y0 - circY) * w]; } } } return radSum; }