opencv - image multiplication

后端 未结 2 959
伪装坚强ぢ
伪装坚强ぢ 2021-01-13 12:29

hi, i\'m trying to play a little bit with Mat class. I want to do a product element wise between two images, the c++/opencv port of MATLAB immultiply.

This is my cod

2条回答
  •  孤街浪徒
    2021-01-13 13:14

    Thanks to Wajih comment i have done some basic test, and some basic debug, and i got i work perfectly. I think this could become a mini tutorial on alpha blending and image multiply, but for now is only a few lines of commented code.

    note that the 2 images must be of the same size.. and for sure some error checking should be done for a solid code..

    Hope it helps someone! And, of course, if you have some hints to make this code more readable or more compact (one-liner guys are very appreciate!) or efficient.. just comment, thank you a lot!

    #include 
    #include 
    #include "opencv2/imgproc/imgproc.hpp"
    
    #include 
    
    using namespace cv;
    using namespace std;
    
    void printMinMax(Mat m, string name) {
        double minVal; 
        double maxVal; 
        Point minLoc; 
        Point maxLoc;
    
        if(m.channels() >1) {
            cout << "ERROR: matrix "<(3,3) << 0,1,2,3,4,5,6,7,255);
        cout << "test Mat 3x3" << endl << imgA << endl;
    
        // not that if a value exceed 255 it is truncated at value%256 
        imgA = (Mat_(3,3) << 0,1, 258 ,3,4,5,6,7,255);
        cout << "test Mat 3x3 with last element truncated to 258%256=2" << endl << imgA << endl;
    
        // create a second matrix
        imgB = Mat(3, 3, CV_8UC1);
        imgB = (Mat_(3,3) << 0,1,2,3,4,5,6,7,8);
    
        // now the matrix product. we are multiplying a value that can goes from 0-255 with another 0-255 value..
        // the edge cases are "min * min" and "max * max", 
        // that means: our product is a function that return a value in the domain 0*0-255*255 ; 0-65025
        // ah, ah! this number exceed the Mat U8C1 domain!, we need different data types. 
        // we need a bigger one.. let's say 32FC1 
    
        Mat imgA_32FC1 = imgA.clone();
        imgA_32FC1.convertTo(imgA_32FC1, CV_32FC1);
        Mat imgB_32FC1 = imgB.clone();
        imgB_32FC1.convertTo(imgB_32FC1, CV_32FC1);
    
        // after conversion.. value are scaled?
        cout << "imgA after conversion:" << endl << imgA_32FC1 << endl;
        cout << "imgB after conversion:" << endl << imgB_32FC1 << endl;
    
        product = imgA_32FC1.mul( imgB_32FC1 );
        // note: the product values are in the range 0-65025
        cout << "the product:" << endl << product << endl;
    
        // now, this does not have much sense, because we started from a 0-255 range Mat and now we have a 0-65025 that is nothing..
        // it is not uchar range and it is not float range (that is a lot bigger than that)
        // so, we can normalize back to 0-255
        // what do i mean with 'normalize' now?
        // i mean: scale all values for a constant that maps 0 to 0 and 65025 to 255..
        product.convertTo(product, CV_32FC1, 1.0f/65025.0f * 255);
        // but it is still a 32FC1.. not as the start matix..
        cout << "the product, normalized back to 0-255, still in 32FC1:" << endl << product << endl;
        product.convertTo(product, CV_8UC1);
        cout << "the product, normalized back to 0-255, now int 8UC1:" << endl << product << endl;
    
        cout << "-----------------------------------------------------------" << endl;
    
        // real stuffs now.
        imgA = imread("test1.jpg"); 
        cvtColor(imgA, imgA, CV_BGR2GRAY);
    
        imgB = imread("test2.jpg"); 
        cvtColor(imgB, imgB, CV_BGR2GRAY);
    
        imgA_32FC1 = imgA.clone();
        imgA_32FC1.convertTo(imgA_32FC1, CV_32FC1);
        imgB_32FC1 = imgB.clone();
        imgB_32FC1.convertTo(imgB_32FC1, CV_32FC1);
    
        product = imgA_32FC1.mul( imgB_32FC1 );
        printMinMax(product, "product");
        product.convertTo(product, CV_32FC1, 1.0f/65025.0f * 255);
        product.convertTo(product, CV_8UC1);
    
        // concat two images in one big image
        imgAB = Mat( max(imgA.rows,imgB.rows), imgA.cols+imgB.cols, imgA.type());
        imgA.copyTo(imgAB(Rect(0, 0, imgA.cols, imgA.rows)));
        imgB.copyTo(imgAB(Rect(imgA.cols, 0, imgB.cols, imgB.rows)));
    
        namedWindow("originals", CV_WINDOW_AUTOSIZE);
        namedWindow("product", CV_WINDOW_AUTOSIZE);
    
        while( true )
        {
            char c = (char)waitKey(10);
    
            if( c == 27 )
                { break; }
    
            imshow( "originals", imgAB );
            imshow( "product", product );
        }
    
        return 0;
    }
    

提交回复
热议问题