Mat lena = Cv2.ImRead("lena.jpg");
// 卡通化
Mat imgBF = new Mat();
Cv2.BilateralFilter(lena, imgBF, 9, 150, 150);
// 丢弃一些颜色
Mat result = imgBF / 25;
result = result * 25;
// 转换到float,为后续乘法做准备
Mat resultF = new Mat();
result.ConvertTo(resultF, MatType.CV_32FC3);
// 中值过滤,去噪点
Mat imgMedian = new Mat();
Cv2.MedianBlur(lena, imgMedian, 7);
// canny 检测边缘
Mat imgCanny = new Mat();
Cv2.Canny(imgMedian, imgCanny, 50, 150);
// 膨胀边缘
Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2, 2));
Cv2.Dilate(imgCanny, imgCanny, kernel);
// 反转,变成黑色,保证边缘是黑色
imgCanny = 255 - imgCanny;
Mat imgCannyF = new Mat();
imgCanny.ConvertTo(imgCannyF, MatType.CV_32FC3);
imgCannyF /= 255;// 取值限制到0~1,为后续乘法做准备
// 模糊平滑边缘线
Cv2.Blur(imgCannyF, imgCannyF, new Size(5, 5));
Mat imgCanny3C = new Mat();
Mat[] imgCanny3Cs = { imgCannyF, imgCannyF, imgCannyF };
Cv2.Merge(imgCanny3Cs, imgCanny3C); // 合并图
Cv2.Multiply(resultF, imgCanny3C, resultF);
resultF.ConvertTo(result, MatType.CV_8UC3);
Cv2.ImShow("lena", lena);
Cv2.ImShow("imgBF", imgBF);
Cv2.ImShow("imgCanny", imgCanny);
Cv2.ImShow("result", result);
Cv2.WaitKey();
lesson5-1.jpg
采取方案为
- 去噪之后采用canny得到边缘
//
// 摘要:
// Finds edges in an image using Canny algorithm.
//
// 参数:
// src:
// Single-channel 8-bit input image
//
// edges:
// The output edge map. It will have the same size and the same type as image
//
// threshold1:
// The first threshold for the hysteresis procedure
//
// threshold2:
// The second threshold for the hysteresis procedure
//
// apertureSize:
// Aperture size for the Sobel operator [By default this is ApertureSize.Size3]
//
// L2gradient:
// Indicates, whether the more accurate L2 norm should be used to compute the image
// gradient magnitude (true), or a faster default L1 norm is enough (false). [By
// default this is false]
public static void Canny(InputArray src, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false);
- 使用双边滤波函数BilateralFilter得到卡通化的底片
双边滤波器可以很好的保存图像边缘细节而滤除掉低频分量的噪音,但是双边滤波器的效率不是太高,花费的时间相较于其他滤波器而言也比较长。
//
// 摘要:
// Applies bilateral filter to the image
//
// 参数:
// src:
// The source 8-bit or floating-point, 1-channel or 3-channel image
//
// dst:
// The destination image; will have the same size and the same type as src
//
// d:
// The diameter of each pixel neighborhood, that is used during filtering. If it
// is non-positive, it's computed from sigmaSpace
//
// sigmaColor:
// Filter sigma in the color space. Larger value of the parameter means that farther
// colors within the pixel neighborhood will be mixed together, resulting in larger
// areas of semi-equal color
//
// sigmaSpace:
// Filter sigma in the coordinate space. Larger value of the parameter means that
// farther pixels will influence each other (as long as their colors are close enough;
// see sigmaColor). Then d>0 , it specifies the neighborhood size regardless of
// sigmaSpace, otherwise d is proportional to sigmaSpace
//
// borderType:
public static void BilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, BorderTypes borderType = BorderTypes.Reflect101);
对于简单的滤波而言,可以将两个sigma值设置成相同的值,如果值<10,则对滤波器影响很小,如果值>150则会对滤波器产生较大的影响,会使图片看起来像卡通。
- 两张图叠加
Cv2.Multiply(resultF, imgCanny3C, resultF);