C++ opencv-图像乘法

C++ opencv-图像乘法,c++,matlab,opencv,multiplication,C++,Matlab,Opencv,Multiplication,嗨,我想和Mat班的同学玩一玩。 我想在两个图像之间创建一个产品元素,即MATLAB的c++/opencv端口 这是我的代码: #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; using namespace

嗨,我想和Mat班的同学玩一玩。 我想在两个图像之间创建一个产品元素,即MATLAB的c++/opencv端口

这是我的代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace cv;
using namespace std;

Mat imgA, imgB;
Mat imgAB;
Mat product;

void printMinMax(Mat m, string s) {
    double minVal; 
    double maxVal; 
    Point minLoc; 
    Point maxLoc;

    minMaxLoc( m, &minVal, &maxVal, &minLoc, &maxLoc );
    cout << "min val in " << s << ": " << minVal << endl;
    cout << "max val in " << s << ": " << maxVal << endl;
}

int main(int /*argc*/, char** /*argv*/) {

    cout << "OpenCV version: " << CV_MAJOR_VERSION << " " << CV_MINOR_VERSION << endl;

    imgA = imread("test1.jpg"); 
    cout << "original image size: " << imgA.rows << " " << imgA.cols << endl;
    cout << "original type: " << imgA.type() << endl;
    cvtColor(imgA, imgA, CV_BGR2GRAY);
    printMinMax(imgA, "imgA");

    imgB = imread("test2.jpg"); 
    cout << "original image size: " << imgB.rows << " " << imgB.cols << endl;
    cout << "original type: " << imgB.type() << endl;
    cvtColor(imgB, imgB, CV_BGR2GRAY);
    printMinMax(imgB, "imgB");

    namedWindow("originals", CV_WINDOW_AUTOSIZE);
    namedWindow("product", CV_WINDOW_AUTOSIZE);

    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)));

    product = imgA.mul(imgB);
    printMinMax(product, "product");

    while( true )
    {
        char c = (char)waitKey(10);

        if( c == 27 )
            { break; }

        imshow( "originals", imgAB );
        imshow( "product", product );
    }

    return 0;
}
我认为乘积中的最大值必须大于255,但会被截断为255,因为两个矩阵的类型是16。
我曾尝试将矩阵转换为CV_32F,但产品中的maxVal是64009(我不理解这个数字)

你是对的,你应该将矩阵imgA,imgB转换为CV32FC1类型。由于此矩阵中的最大值为255,因此最大可能值为65025。但是,imgA和imgB的最大值可能不在同一位置,因此64009是很有可能的。

多亏了我做了一些基本测试和一些基本调试,我工作得很好。我认为这可能成为一个关于alpha混合和图像倍增的迷你教程,但目前只有几行注释代码

请注意,这两个图像的大小必须相同。。当然,应该对可靠的代码进行一些错误检查

希望它能帮助别人!当然,如果您有一些提示可以使代码更可读或更紧凑(单行程序的人非常欣赏!)或更高效。。评论一下,非常感谢

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

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 "<<name<<" must have 1 channel for calling minMaxLoc" << endl;
    }

    minMaxLoc( m, &minVal, &maxVal, &minLoc, &maxLoc );
    cout << "min val in " << name << ": " << minVal << " in loc: " << minLoc << endl;
    cout << "max val in " << name << ": " << maxVal << " in loc: " << maxLoc << endl;
}

int main(int /*argc*/, char** /*argv*/) {

    cout << "OpenCV version: " << CV_MAJOR_VERSION << " " << CV_MINOR_VERSION << endl; // 2 4

    Mat imgA, imgB;
    Mat imgAB;
    Mat product;

    // fast matrix creation, comma-separated initializer
    // example1: create a matrix with value from 0 to 255
    imgA = Mat(3, 3, CV_8UC1);
    imgA = (Mat_<uchar>(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_<uchar>(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_<uchar>(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;
}
#包括
#包括
#包括“opencv2/imgproc/imgproc.hpp”
#包括
使用名称空间cv;
使用名称空间std;
void printMinMax(材料m,字符串名称){
双米瓦尔;
双最大值;
明洛克点;
maxLoc点;
如果(m.通道()>1){

我可以先尝试一个小的3x1和1x3矩阵,看看你做的乘法是否正确。是的,很好的建议。无论如何,我想做元素乘法,而不是矩阵积,所以我认为2矩阵的大小应该相等,但要确保你做的是正确的积。你不能做1x255的事情,并且期望有差异不同于255的结果。哦,还有一件事,mate:)尝试初始化“产品”矩阵,我不知道你的图像是否是彩色的,但可能是类型为CV_8UCx,这会截断你的结果。检查类型,然后初始化一大堆mate!现在“如何工作”更清楚了,请看我自己的答案!
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

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 "<<name<<" must have 1 channel for calling minMaxLoc" << endl;
    }

    minMaxLoc( m, &minVal, &maxVal, &minLoc, &maxLoc );
    cout << "min val in " << name << ": " << minVal << " in loc: " << minLoc << endl;
    cout << "max val in " << name << ": " << maxVal << " in loc: " << maxLoc << endl;
}

int main(int /*argc*/, char** /*argv*/) {

    cout << "OpenCV version: " << CV_MAJOR_VERSION << " " << CV_MINOR_VERSION << endl; // 2 4

    Mat imgA, imgB;
    Mat imgAB;
    Mat product;

    // fast matrix creation, comma-separated initializer
    // example1: create a matrix with value from 0 to 255
    imgA = Mat(3, 3, CV_8UC1);
    imgA = (Mat_<uchar>(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_<uchar>(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_<uchar>(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;
}