OpenCV (Emgu.CV) — compositing images with alpha

后端 未结 4 2114
刺人心
刺人心 2020-12-31 20:21

I\'m using Emgu.CV to perform some basic image manipulation and composition. My images are loaded as Image.

Question #1:

4条回答
  •  无人及你
    2020-12-31 21:11

    Using Osiris's suggestion as a starting point, and having checked out alpha compositing on Wikipedia, i ended up with the following which worked really nicely for my purposes.

    This was used this with Emgucv. I was hoping that the opencv gpu::AlphaComposite methods were available in Emgucv which I believe would have done the following for me, but alas the version I am using didn't appear to have them implemented.

    static public Image Overlay( Image image1, Image image2 )
            {
    
                Image result = image1.Copy();
                Image src = image2;
                Image dst = image1;
    
                int rows = result.Rows;
                int cols = result.Cols;
                for (int y = 0; y < rows; ++y)
                {
                    for (int x = 0; x < cols; ++x)
                    {
                        // http://en.wikipedia.org/wiki/Alpha_compositing
                        double  srcA = 1.0/255 * src.Data[y, x, 3];
                        double dstA = 1.0/255 * dst.Data[y, x, 3];
                        double outA = (srcA + (dstA - dstA * srcA));
                        result.Data[y, x, 0] = (Byte)(((src.Data[y, x, 0] * srcA) + (dst.Data[y, x, 0] * (1 - srcA))) / outA);  // Blue
                        result.Data[y, x, 1] = (Byte)(((src.Data[y, x, 1] * srcA) + (dst.Data[y, x, 1] * (1 - srcA))) / outA);  // Green
                        result.Data[y, x, 2] = (Byte)(((src.Data[y, x, 2] * srcA) + (dst.Data[y, x, 2] * (1 - srcA))) / outA); // Red
                        result.Data[y, x, 3] = (Byte)(outA*255);
                    }
                }
                return result;
            }
    

    A newer version, using emgucv methods. rather than a loop. Not sure it improves on performance. double unit = 1.0 / 255.0; Image[] dstS = dst.Split(); Image[] srcS = src.Split(); Image[] rs = result.Split();

            Image srcA = srcS[3] * unit;
            Image dstA = dstS[3] * unit;
            Image outA = srcA.Add(dstA.Sub(dstA.Mul(srcA)));// (srcA + (dstA - dstA * srcA));
    
            // Red.
            rs[0] = srcS[0].Mul(srcA).Add(dstS[0].Mul(1 - srcA)).Mul(outA.Pow(-1.0)); // Mul.Pow is divide.
            rs[1] = srcS[1].Mul(srcA).Add(dstS[1].Mul(1 - srcA)).Mul(outA.Pow(-1.0));
            rs[2] = srcS[2].Mul(srcA).Add(dstS[2].Mul(1 - srcA)).Mul(outA.Pow(-1.0));
            rs[3] = outA.Mul(255);
    
            // Merge image back together.
            CvInvoke.cvMerge(rs[0], rs[1], rs[2], rs[3], result);
            return result.Convert();
    

提交回复
热议问题