//Grabcut分割函数封装 private Mat grabCut(Mat image, int ITER_COUNT, GrabCutModes GRABCUTMODE, int x, int y, int w, int h) { var bgModel = new Mat(); var fgdModel = new Mat(); var bgModel1 = new Mat(); var fgdModel1 = new Mat(); var mask = new Mat(); const int GC_PR_FGD = 3; Rect rect = new Rect(); rect.X = x; rect.Y = y; rect.Width = w; rect.Height = h; Cv2.GrabCut(image, mask, rect, bgModel, fgdModel, ITER_COUNT, GRABCUTMODE); Cv2.Compare(mask, GC_PR_FGD, mask, CmpTypes.EQ); Mat foreground = new Mat(image.Size(), MatType.CV_8UC3, new Scalar(0, 0, 0)); image.CopyTo(foreground, mask); showRect(rect.X, rect.Y, rect.Width, rect.Height); showImagePara(image); return(foreground); }
//更改参数再次分割图片 private void button4_Click(object sender, EventArgs e) { if (comboBox1.Text == "grabcut" && value1.Text == "迭代次数:" && value2.Text == "分割算子:") { try { int iter_count = int.Parse(textBox5.Text); GrabCutModes grabcutmode = (GrabCutModes)(Enum.Parse(typeof(GrabCutModes), comboBox4.Text)); int x = int.Parse(textBox7.Text); int y = int.Parse(textBox8.Text); int w = int.Parse(textBox9.Text); int h = int.Parse(textBox10.Text); if (iter_count > 20 || iter_count < 0) { MessageBox.Show("迭代次数于0-20次之内较为合适"); } else { System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)pictureBox1.Image; Mat image = BitmapConverter.ToMat(bitmap); double startTime = Cv2.GetTickCount(); Mat res = grabCut(image, iter_count, grabcutmode, x, y, w, h); double duration = (Cv2.GetTickCount() - startTime) / (Cv2.GetTickFrequency()); showImage(res, duration); showParameters("迭代次数:", iter_count.ToString(), "分割算子:", grabcutmode.ToString()); textBox6.Hide(); showRect(x, y, w, h); } } catch (Exception err) { if (err.ToString().Contains("totalSampleCount")) { MessageBox.Show("您选择的区域无法分割出前景,无法分割,请重新选择区域大小"); } else if (err.ToString().Contains("mask")) { MessageBox.Show("掩模mask为空,无法分割"); } else if (err.ToString().Contains("Format")) { MessageBox.Show("输入的字符串格式不正确,请重新输入"); } } } if (comboBox1.Text == "watershed" && value1.Text == "中值滤波内核:" && value2.Text == "形态学卷积核:") { try { if (int.Parse(textBox5.Text) % 2 == 0) { MessageBox.Show("中值滤波内核应为奇数,请重新输入。"); } else { int meadianblur_ksize = int.Parse(textBox5.Text); if (meadianblur_ksize > 1000 || meadianblur_ksize < 0) { MessageBox.Show("数值不合理,请重新输入适当的数值"); } else { string text = textBox6.Text; string diff11 = text.Replace("(", string.Empty); string diff12 = diff11.Replace(")", string.Empty); string[] str = diff12.Split(','); Size element_size = new Size(int.Parse(str[0]), int.Parse(str[1])); System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)pictureBox1.Image; Mat image = BitmapConverter.ToMat(bitmap); double startTime = Cv2.GetTickCount(); Mat result = waterShed(image, meadianblur_ksize, element_size); double duration = (Cv2.GetTickCount() - startTime) / (Cv2.GetTickFrequency()); showImage(result, duration); showParameters("中值滤波内核:", meadianblur_ksize.ToString(), "形态学卷积核:", "(" + element_size.Width.ToString() + "," + element_size.Height.ToString() + ")"); } } } catch (Exception err) { if (err.ToString().Contains("Format")) { MessageBox.Show("输入的字符串格式不正确,请重新输入"); } else if (err.ToString().Contains("索引超出了数组界限")) { MessageBox.Show("形态学卷积内核应用英文括号隔开"); } else { MessageBox.Show(err.ToString()); } } } if (comboBox1.Text == "meanshift" && value1.Text == "颜色域半径:" && value2.Text == "空间域半径:") { try { int meanshift_sp = int.Parse(textBox5.Text); int meanshift_sr = int.Parse(textBox6.Text); if (meanshift_sp < 0 || meanshift_sr < 0 || meanshift_sp > 1000 || meanshift_sr > 1000) { MessageBox.Show("参数有误或数值过大,请重新输入数据"); } else { System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)pictureBox1.Image; Mat image = BitmapConverter.ToMat(bitmap); double startTime = Cv2.GetTickCount(); Mat res = meanShift(image, meanshift_sp, meanshift_sr); double duration = (Cv2.GetTickCount() - startTime) / (Cv2.GetTickFrequency()); showImage(res, duration); showParameters("颜色域半径:", meanshift_sp.ToString(), "空间域半径:", meanshift_sr.ToString()); } } catch (Exception err) { if (err.ToString().Contains("Format")) { MessageBox.Show("输入的字符串格式不正确,请重新输入"); } else { MessageBox.Show(err.ToString()); } } } if (comboBox1.Text == "floodfill" && value1.Text == "像素最大下行差异值:" && value2.Text == "像素最大上行差异值:") { try { string diff1 = textBox5.Text; string diff11 = diff1.Replace("[", string.Empty); string diff12 = diff11.Replace("]", string.Empty); string[] str1 = diff12.Split(','); Scalar lodiff = new Scalar(int.Parse(str1[0]), int.Parse(str1[1]), int.Parse(str1[2]), int.Parse(str1[3])); string diff2 = textBox6.Text; string diff21 = diff2.Replace("[", string.Empty); string diff22 = diff21.Replace("]", string.Empty); string[] str2 = diff22.Split(','); int x = int.Parse(textBox7.Text); int y = int.Parse(textBox8.Text); int w = int.Parse(textBox9.Text); int h = int.Parse(textBox10.Text); Scalar updiff = new Scalar(int.Parse(str2[0]), int.Parse(str2[1]), int.Parse(str2[2]), int.Parse(str2[3])); System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)pictureBox1.Image; Mat image = BitmapConverter.ToMat(bitmap); double startTime = Cv2.GetTickCount(); Mat res = floodFill(image, lodiff, updiff, x, y, w, h); double duration = (Cv2.GetTickCount() - startTime) / (Cv2.GetTickFrequency()); showImage(res, duration); showRect(x, y, w, h); showParameters("像素最大下行差异值:", lodiff.ToString(), "像素最大上行差异值:", updiff.ToString()); } catch (Exception err) { if (err.ToString().Contains("Format")) { MessageBox.Show("输入的字符串格式不正确,请重新输入(应输入英文逗号)"); } else if (err.ToString().Contains("索引超出了数组界限")) { MessageBox.Show("像素最大下(上)行差异值应用英文括号隔开"); } else { MessageBox.Show(err.ToString()); } } } if (comboBox1.Text == "contour" && value1.Text == "高斯核x方向标准差:" && value2.Text == "二值化算子:") { try { ThresholdTypes contour_type = (ThresholdTypes)(Enum.Parse(typeof(ThresholdTypes), comboBox4.Text)); int sigmax = int.Parse(textBox5.Text); System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)pictureBox1.Image; Mat image = BitmapConverter.ToMat(bitmap); double startTime = Cv2.GetTickCount(); Mat res = contourSeg(image, contour_type, sigmax); double duration = (Cv2.GetTickCount() - startTime) / (Cv2.GetTickFrequency()); showImage(res, duration); showParameters("高斯核x方向标准差:", sigmax.ToString(), "二值化算子:", contour_type.ToString()); textBox6.Hide(); } catch (Exception err) { if (err.ToString().Contains("Format")) { MessageBox.Show("输入的字符串格式不正确,请重新输入"); } else if (err.ToString().Contains("索引超出了数组界限")) { MessageBox.Show("索引超出了数组界限,无法分割"); } else { MessageBox.Show(err.ToString()); } } } }
/// <summary> /// Segments the image using GrabCut algorithm /// </summary> /// <param name="img">Input 8-bit 3-channel image.</param> /// <param name="mask">Input/output 8-bit single-channel mask. /// The mask is initialized by the function when mode is set to GC_INIT_WITH_RECT. /// Its elements may have Cv2.GC_BGD / Cv2.GC_FGD / Cv2.GC_PR_BGD / Cv2.GC_PR_FGD</param> /// <param name="rect">ROI containing a segmented object. The pixels outside of the ROI are /// marked as "obvious background". The parameter is only used when mode==GC_INIT_WITH_RECT.</param> /// <param name="bgdModel">Temporary array for the background model. Do not modify it while you are processing the same image.</param> /// <param name="fgdModel">Temporary arrays for the foreground model. Do not modify it while you are processing the same image.</param> /// <param name="iterCount">Number of iterations the algorithm should make before returning the result. /// Note that the result can be refined with further calls with mode==GC_INIT_WITH_MASK or mode==GC_EVAL .</param> /// <param name="mode">Operation mode that could be one of GrabCutFlag value.</param> public static void GrabCut(InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, GrabCutModes mode) { if (img == null) throw new ArgumentNullException(nameof(img)); if (mask == null) throw new ArgumentNullException(nameof(mask)); if (bgdModel == null) throw new ArgumentNullException(nameof(bgdModel)); if (fgdModel == null) throw new ArgumentNullException(nameof(fgdModel)); img.ThrowIfDisposed(); mask.ThrowIfNotReady(); bgdModel.ThrowIfNotReady(); fgdModel.ThrowIfNotReady(); NativeMethods.imgproc_grabCut(img.CvPtr, mask.CvPtr, rect, bgdModel.CvPtr, fgdModel.CvPtr, iterCount, (int)mode); GC.KeepAlive(img); mask.Fix(); bgdModel.Fix(); fgdModel.Fix(); }
/// <summary> /// Segments the image using GrabCut algorithm. /// The input is 8-bit 3-channel image. /// </summary> /// <param name="mask">Input/output 8-bit single-channel mask. /// The mask is initialized by the function when mode is set to GC_INIT_WITH_RECT. /// Its elements may have Cv2.GC_BGD / Cv2.GC_FGD / Cv2.GC_PR_BGD / Cv2.GC_PR_FGD</param> /// <param name="rect">ROI containing a segmented object. The pixels outside of the ROI are /// marked as "obvious background". The parameter is only used when mode==GC_INIT_WITH_RECT.</param> /// <param name="bgdModel">Temporary array for the background model. Do not modify it while you are processing the same image.</param> /// <param name="fgdModel">Temporary arrays for the foreground model. Do not modify it while you are processing the same image.</param> /// <param name="iterCount">Number of iterations the algorithm should make before returning the result. /// Note that the result can be refined with further calls with mode==GC_INIT_WITH_MASK or mode==GC_EVAL .</param> /// <param name="mode">Operation mode that could be one of GrabCutFlag value.</param> public void GrabCut(InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, GrabCutModes mode) { Cv2.GrabCut(this, mask, rect, bgdModel, fgdModel, iterCount, mode); }