Wasim Karani
Wasim Karani

Reputation: 8886

Overlaying transparent image over output of camera in opencv

I have transparent images [shown below] and I am trying to overlay it with aishack.in cvOverlayImage() function to overlay it on camera source

cvOverlayImage()

    void cvOverlayImage(IplImage* src, IplImage* overlay, CvPoint location, CvScalar S, CvScalar D)
    {
     int x,y,i;

      for(x=0;x < overlay->width -10;x++)
        {
            if(x+location.x>=src->width) continue;
            for(y=0;y < overlay->height -10;y++)
            {
                if(y+location.y>=src->height) continue;
                CvScalar source = cvGet2D(src, y+location.y, x+location.x);
                CvScalar over = cvGet2D(overlay, y, x);
                CvScalar merged;
                for(i=0;i<4;i++)
                merged.val[i] = (S.val[i]*source.val[i]+D.val[i]*over.val[i]);
                cvSet2D(src, y+location.y, x+location.x, merged);
            }
        }
    }

calling cvOverlayImage()

cvOverlayImage(image_n, neg_img, cvPoint(0, 0), cvScalar(1.0,1.0,1.0,1.0), cvScalar(0.1,0.1,0.1,0.1));

Inputs to cvOverlayImage()

  1. Camera Capture

Camera Capture

  1. Negative Image

Negative Image

Output from cvOverlayImage()

Output

As you can see I am not getting what I need.Please help me.

Upvotes: 0

Views: 5145

Answers (3)

Clemens Helm
Clemens Helm

Reputation: 3971

I think what you want to achieve is not addition but multiplication:

int multiplicator = over.val[i] / 255 // 0 for black, 1 for white
merged.val[i] = source.val[i] * multiplicator;

This way the pixel value will be the original value for a white overlay pixel and black for a black overlay pixel.

Upvotes: 0

Gustavo Litovsky
Gustavo Litovsky

Reputation: 2487

One solution I used is to simply detect where the white is present and in those cases simply use the pixel from the source picture. Otherwise use the overlay picture's pixel. Worked well for me for a similar situation. Also, if the picture you load has the alpha channel and can be used as a mask, that's even better.

void cvOverlayImage(IplImage* src, IplImage* overlay, CvPoint location, 
CvScalar S, CvScalar D)
{
 int x,y,i;

  for(x=0;x < overlay->width;x++)
    {
        if(x+location.x>=src->width) continue;
        for(y=0;y < overlay->height;y++)
        {
            if(y+location.y>=src->height) continue;
            CvScalar source = cvGet2D(src, y+location.y, x+location.x);
            CvScalar over = cvGet2D(overlay, y, x);
            CvScalar merged;
            if(over.val[0] == 255 && over.val[1] == 255 && over.val[2] == 255 && over.val[3] == 255)
            {
                // White pixel so don't overlay
                for(i=0;i<4;i++)
                    merged.val[i] = (source.val[i]);
            }
            else
            {
                for(i=0;i<4;i++)
                    merged.val[i] = (over.val[i]);

            }

            cvSet2D(src, y+location.y, x+location.x, merged);
        }
    }
}

Upvotes: 2

Smash
Smash

Reputation: 3802

This isn't tested, but shouldn't S[i]+D[i] = 1 to preserve the total intensity ?

Upvotes: 1

Related Questions