public void Apply(Mat src) { using (ResourceTracker t = new ResourceTracker()) { Stopwatch sw = new Stopwatch(); sw.Start(); Size srcSize = src.Size(); //todo: 只对脸部进行亮肤https://blog.csdn.net/cnbloger/article/details/77949949 //https://blog.csdn.net/skyqsdyy/article/details/89467143 //todo: 对src进行美颜、瘦脸、亮肤等。只要控制在一帧50ms之内即可。 Mat matMask = t.NewMat(srcSize, MatType.CV_8UC1, new Scalar(0)); RenderGreenScreenMask(src, matMask); //the area is by integer instead of double, so that it can improve the performance of comparision of areas int minBlockArea = (int)(srcSize.Width * srcSize.Height * this.MinBlockPercent); var contoursExternalForeground = Cv2.FindContoursAsArray(matMask, RetrievalModes.External, ContourApproximationModes.ApproxNone) .Select(c => new { contour = c, Area = (int)Cv2.ContourArea(c) }) .Where(c => c.Area >= minBlockArea) .OrderByDescending(c => c.Area).Take(5).Select(c => c.contour); //contoursExternalForeground = contoursExternalForeground.Select(c=>Cv2.ApproxPolyDP(c,0.5,true)); //a new Mat used for rendering the selected Contours var matMaskForeground = t.NewMat(srcSize, MatType.CV_8UC1, new Scalar(0)); //thickness: -1 means filling the inner space matMaskForeground.DrawContours(contoursExternalForeground, -1, new Scalar(255), thickness: -1); //matInternalHollow is the inner Hollow parts of body part. var matInternalHollow = t.NewMat(srcSize, MatType.CV_8UC1, new Scalar(0)); Cv2.BitwiseXor(matMaskForeground, matMask, matInternalHollow); int minHollowArea = (int)(minBlockArea * 0.5);//the lower size limitation of InternalHollow is less than minBlockArea, because InternalHollows are smaller //find the Contours of Internal Hollow var contoursInternalHollow = Cv2.FindContoursAsArray(matInternalHollow, RetrievalModes.External, ContourApproximationModes.ApproxNone) .Select(c => new { contour = c, Area = Cv2.ContourArea(c) }) .Where(c => c.Area >= minHollowArea) .OrderByDescending(c => c.Area).Take(10).Select(c => c.contour); //draw hollows foreach (var c in contoursInternalHollow) { matMaskForeground.FillConvexPoly(c, new Scalar(0)); } var element = t.T(Cv2.GetStructuringElement(MorphShapes.Cross, new Size(3, 3))); //smooth the edge of matMaskForeground Cv2.MorphologyEx(matMaskForeground, matMaskForeground, MorphTypes.Close, element, iterations: 6); Cv2.GaussianBlur(matMaskForeground, matMaskForeground, new Size(3, 3), 0, 0); var foreground = t.NewMat(src.Size(), MatType.CV_8UC4, new Scalar(0)); ZackCVHelper.AddAlphaChannel(src, foreground, matMaskForeground); //resize the _backgroundImage to the same size of src Cv2.Resize(_backgroundImage, src, src.Size()); //draw foreground(people) on the backgroundimage ZackCVHelper.DrawOverlay(src, foreground); Debug.WriteLine($"5:{sw.ElapsedMilliseconds}"); } }
static void BeautyIt(Mat src) { using (ResourceTracker t = new ResourceTracker()) { Mat dst = t.NewMat(); Cv2.BilateralFilter(src, dst, 15, 35, 35); dst.CopyTo(src); } }
static void Main(string[] args) { using (ResourceTracker t = new ResourceTracker()) { Mat picMat = t.T(Cv2.ImRead("bg.png")); Mat mat1 = t.T(255 - picMat); Mat mat2 = t.T(np.zeros_like(mat1)); Mat mat3 = t.NewMat(); Mat mat4 = t.T(np.array(new byte[] { 33, 88, 99 })); Mat mat5 = t.T(np.array(33, 88, 99)); Mat mat6 = t.T(255 - t.T(picMat * 0.8)); Mat[] mats1 = t.T(picMat.Split()); Mat[] mats2 = new Mat[] { mats1[0], mats1[1], mats1[2], t.T(np.zeros_like(picMat)) }; Cv2.Merge(mats2, mat3); } using (ResourceTracker t = new ResourceTracker()) { Mat mat1 = t.NewMat(new Size(100, 100), MatType.CV_8UC3, new Scalar(0)); Mat mat3 = t.T(255 - t.T(mat1 * 0.8)); Mat[] mats1 = t.T(mat3.Split()); Mat mat4 = t.NewMat(); Cv2.Merge(new Mat[] { mats1[0], mats1[1], mats1[2] }, mat4); } using (ResourceTracker t = new ResourceTracker()) { var img1 = t.T(Cv2.ImRead("bg.png")); var img2 = t.T(Cv2.ImRead("2.jpg")); var img2_resized = t.T(np.zeros_like(img1)); Cv2.Resize(img2, img2_resized, img1.Size()); var img3 = t.T(np.zeros_like(img1)); np.where < Vec3b > (img1, img3, p => p.Item0 < 100 || p.Item1 < 100, img1, img2_resized); Cv2.ImShow("a", img3); Cv2.WaitKey(); } }