0

I want to blend two images like multiply blending in photoshop , i want to do the same in OpenCv using C++ for my app , I visit this many time and try to understand every time but i didn't get it , i search it alot but didn't get what i want other then this but this is little bit strange as conversion is alot from IplImages to ibl etc , Any help , guide, idea and example related opencv is needed . I go through Addweight but i think its quite different from Multiply Blending

Formula which i saw here

Target * Blend

and below is what i tried

Mat img1 = imread("E:\\img.jpg");
Mat img2 = Mat (img1.size(),img1.type());
vector<Mat> colors_1;
split(img2, colors_1);
colors_1[0] = 113;
colors_1[1] = 221;
colors_1[2] = 216;
merge(colors_1,img2);
Mat result(img1.size(), CV_32F);
for(int i = 0; i < img1.size().height; ++i){
    for(int j = 0; j < img1.size().width; ++j){
        for (int rgb=0 ; rgb<=img1.channels();rgb++){
            float target = float(img1.at<uchar>(i, j)) / 255;
            float blend = float(img2.at<uchar>(i, j)) / 255;
            result.at<float>(i, j) = target*blend;
        }

    }
}  

Result is in GrayScale and its not looking exact

Thank you

Community
  • 1
  • 1
AHF
  • 1,070
  • 2
  • 15
  • 47

1 Answers1

1

You are not accessing the image channels correctly. Moreover, you do not need to store the result in a float image, uchar is OK. Also, your loop on RGB channels should end when rgb<img1.channels().

Try this code:

cv::Mat img1 = cv::imread("E:\\img.jpg");
cv::Mat img2 = cv::Mat (img1.size(),img1.type());
std::vector<cv::Mat> colors_1;
cv::split(img2, colors_1);
colors_1[0] = 113;
colors_1[1] = 221;
colors_1[2] = 216;
cv::merge(colors_1,img2);
cv::Mat result(img1.size(), CV_8UC3);
for(int i = 0; i < img1.rows; ++i){
    for(int j = 0; j < img1.cols; ++j){
        for (int c=0 ; c<img1.channels();c++){
            uchar target = img1.at<uchar>(i, 3*j+c);
            uchar blend = img2.at<uchar>(i, 3*j+c);
            result.at<uchar>(i, 3*j+c) = cv::saturate_cast<uchar>(target*blend/255.);
        }
    }
}  
BConic
  • 8,750
  • 2
  • 29
  • 55
  • +1 , but when i want to change the equation like this `result.at(i, 3*j+c) = cv::saturate_cast(((1-(1-target))/blend)/255.) ;` Can you please tell me why its giving the black image – AHF Apr 24 '14 at 13:32
  • Try to understand what is done by `cv::saturate_cast(target*blend/255.)` in my example: `target` and `blend` have a range of [0,255] and `result` must have a range of [0,255], which is why `target*blend/255.` is valid. In your case `((1-(1-target))/blend)/255.` has a range of [0,1/255.], which, converted to `uchar` by `cv::saturate_cast(...)`, always gives `0`. – BConic Apr 24 '14 at 15:39
  • Thnks for nice explanation , but when i did it without `/255` it show me black image too – AHF Apr 24 '14 at 17:53
  • yes but this is what i am asking thats why i assume the other formula that how i can fix it to this range – AHF Apr 25 '14 at 05:41
  • @Ahmad Ok, the case of the divide operator is particular. I would do the following: `cv::saturate_cast(target*255./(blend==0?1:blend));`. NB: the `(?:)` conditionnal operator avoids division by zero. – BConic Apr 25 '14 at 06:54