3
$\begingroup$

I am using OpenCV C++ for making the blending mode like in photoshop, I want to make overlay mode in it. I search its alternate in OpenCV in which I found this blending way, but its not the overlay as I want to use the overlay method in it.

Overlay method formula from this documentation

(Target > 0.5) * (1 - (1-2*(Target-0.5)) * (1-Blend)) +
(Target <= 0.5) * ((2*Target) * Blend)

Can anyone please explain this formula for implementation in OpenCV C++ , how I can easily understand it for implementation or is there any already build in function for it or any other easy way out.

$\endgroup$
1
$\begingroup$

You can find many ready solution in the Internet. For example here following macro is given:

#define ChannelBlend_Overlay(A,B)    ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255)))

Additionally you might want to check this package: blImage for source code as you can very easilly translate it. I am sure you will find what you are looking for.

$\endgroup$
  • $\begingroup$ i don't know how to use these macro's as i seen them before . i didnt understand them well $\endgroup$ – ARG Apr 26 '14 at 8:07
1
$\begingroup$

Thanks all for answer and interest but as I didn't found the answer completely following my question , I update my own solution which I get from here

First, the author of the link you provided assumed that a pixel color as a value between 0 and 1.

Imagine you want to blend 2 images img1 and img2. The formula says that if a pixel in img1 as a value Target > 0.5 then the resulting value is (1 - (1-2*(Target-0.5)) * (1-Blend)) for the blended image where Blend is the value of the pixel of img2.

On the other hand, if Target <= 0.5 the resulting color value will be ((2*Target) * Blend).

You need to do this for each pixel.

This link provides an overlay blending function with OpenCV.

Here is an example with a grayscale image. For a RGB image, you need to do this for each channel. Of course img1 and img2 must have the same size. Maybe there is a quicker way to do it with OpenCV.

Mat img1;
Mat img2;
img1 = imread("img1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
img2 = imread("img2.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat result(img1.size(), CV_32F);

for(int i = 0; i < img1.size().height; ++i){
    for(int j = 0; j < img1.size().width; ++j){
        float target = float(img1.at<uchar>(i, j)) / 255;
        float blend = float(img2.at<uchar>(i, j)) / 255;
        if(target > 0.5){
            result.at<float>(i, j) = (1 - (1-2*(target-0.5)) * (1-blend));
        }
        else{
            result.at<float>(i, j) = ((2*target) * blend);
        }
    }
}
$\endgroup$
0
$\begingroup$

Ok. Lets break it into pieces:

(Target > 0.5) * (1 - (1-2*(Target-0.5)) * (1-Blend)) + (Target <= 0.5) * ((2*Target) * Blend)

has two parts that are being blended:

(Target > 0.5) * (1 - (1-2*(Target-0.5))
(Target <= 0.5) * (2*Target)

Of these the first is making sure that pixels with intensity greater than 0.5 (Target > 0.5) only are chosen and the rest (Target <= 0.5) go to the other image. So, the second is limited to 0-0.5 values, which is being scaled to 0-1. For obtaining a similar range for the first set of pixels, a stretching algorithm is being used: 1-(1-2*(Target-0.5)).

As the documentation mentions, this is a combination of multiply and screen - multiply for pixels with values less than or equal to 0.5 and screen for the rest.

Coming to the point of OpenCV implementation, you will require the following methods:

  1. Blend (I1 *(1-b) + I2 *b)

  2. Addition (I1 + I2, with normalization of course)

  3. Inversion (I2 = 1 - I1)

  4. Thresholding (I2 = I1 > a/b)

I have followed the documentation's convention of using 1 as the maximum intensity, you could stick to this using float type images or scale it appropriately to use other formats.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.