/// <summary> /// Selection based on pixel similarity in HSV color space /// </summary> public static unsafe Bitmap Similiar_HSV(Bitmap image, Rectangle rect, List <HSV> hsvs, int similarity) { Bitmap dest = (Bitmap)image.Clone(); if (hsvs.Count == 0) { return(dest); } BitmapData srcDat = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat); BitmapData dstDat = dest.LockBits(rect, ImageLockMode.ReadWrite, dest.PixelFormat); int width = rect.Width; int height = rect.Height; int stride = srcDat.Stride; // get pixel size int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; int offset = stride - width * pixelSize; // do the job byte *src = (byte *)srcDat.Scan0.ToPointer(); byte *dst = (byte *)dstDat.Scan0.ToPointer(); //H = 0 ~ 3066 //S = 0 ~ 511 //V = 0 ~ 511 const int HSV_num = 3067 + 512 + 512; int[] table_mix = new int[HSV_num]; for (int i = 0; i < HSV_num; i++) { table_mix[i] = -1; } int total_l; foreach (HSV hsv in hsvs) { total_l = hsv.Hue + hsv.Saturation + hsv.Value; for (int i = 0; i < similarity / 2; i++) { if ((total_l + i) < HSV_num) { table_mix[total_l + i] = 1; } if ((total_l - i) >= 0) { table_mix[total_l - i] = 1; } } } int koba; // for each row for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, src += pixelSize, dst += pixelSize) { HSV hsv = HSV.FromRGB(new RGB(src[RGB.R], src[RGB.G], src[RGB.B])); koba = hsv.Hue + hsv.Saturation + hsv.Value; if (table_mix[koba] == 1) { dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 0; } else { dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 255; } } src += offset; dst += offset; } image.UnlockBits(srcDat); dest.UnlockBits(dstDat); return(dest); }
/// <summary> /// Stretch HSV histogram to create new image /// </summary> public static unsafe Bitmap HistogramStretchHSV(Bitmap image, Rectangle rect) { Bitmap dest = (Bitmap)image.Clone(); BitmapData srcDat = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat); BitmapData dstDat = dest.LockBits(rect, ImageLockMode.ReadWrite, dest.PixelFormat); int width = rect.Width; int height = rect.Height; int stride = srcDat.Stride; // get pixel size int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; int offset = stride - width * pixelSize; // do the job byte *src = (byte *)srcDat.Scan0.ToPointer(); byte *dst = (byte *)dstDat.Scan0.ToPointer(); int pix_num = width * height; //縦×横 int[] num_b = new int[512]; int min_per, max_per; int per1 = pix_num / 100; int per99 = pix_num / 100 * 99; int[] aryH = new int[pix_num]; int[] aryS = new int[pix_num]; int[] aryV = new int[pix_num]; int maxH, maxS, maxV; int minV; maxH = maxS = maxV = 0; minV = 255; int tmp_pix, last_pix; double ratio; int pos; int count_i = 0; int sum = 0; RGB rgb = new RGB(); HSV hsv = new HSV(); // RGB histograms // for each row for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, src += pixelSize) { rgb.Red = src[RGB.R]; rgb.Green = src[RGB.G]; rgb.Blue = src[RGB.B]; hsv = HSV.FromRGB(rgb); pos = y * width + x; aryH[pos] = hsv.Hue; aryS[pos] = hsv.Saturation; aryV[pos] = hsv.Value; if (hsv.Hue > maxH) { maxH = hsv.Hue; } if (hsv.Saturation > maxS) { maxS = hsv.Saturation; } if (hsv.Value > maxV) { maxV = hsv.Value; } if (hsv.Value < minV) { minV = hsv.Value; } } src += offset; } // histogram for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, src += pixelSize) { num_b[aryV[y * width + x]]++; } } do { sum += num_b[count_i++]; } while (sum < per1); min_per = count_i - 1; do { sum += num_b[count_i++]; } while (sum < per99); max_per = count_i - 1; ratio = (double)(511.0 / (max_per - min_per)); // stretch histogram for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, src += pixelSize) { pos = y * width + x; tmp_pix = aryV[pos]; if (tmp_pix <= min_per) { last_pix = 0; } else if (tmp_pix >= max_per) { last_pix = 511; } else { last_pix = (int)((tmp_pix - min_per) * ratio); } if (last_pix < 0) { aryV[pos] = 0; } else if (last_pix >= 511) { aryV[pos] = 511; } else { aryV[pos] = last_pix; } } } // for each row for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, src += pixelSize, dst += pixelSize) { pos = y * width + x; hsv.Hue = aryH[pos]; hsv.Saturation = aryS[pos]; hsv.Value = aryV[pos]; HSV.ToRGB(hsv, rgb); dst[RGB.R] = rgb.Red; dst[RGB.G] = rgb.Green; dst[RGB.B] = rgb.Blue; } src += offset; dst += offset; } image.UnlockBits(srcDat); dest.UnlockBits(dstDat); return(dest); }