opencv - 图像乘法 [英] opencv - image multiplication

查看:311
本文介绍了opencv - 图像乘法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想和Mat类玩一点。
我想在两个图像之间做一个产品元素,MATLAB的c ++ / opencv端口

这是我的代码:

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

#include< iostream>

using namespace cv;
using namespace std;

Mat imgA,imgB;
Mat imgAB;
垫产品;

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<< 原始图像大小:< imgA.rows<< < imgA.cols < endl;
cout<< original type:<< imgA.type()<< endl;
cvtColor(imgA,imgA,CV_BGR2GRAY);
printMinMax(imgA,imgA);

imgB = imread(test2.jpg);
cout<< 原始图像大小:< 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;
}

这里是结果:

  OpenCV版本:2 4 
原始图片大小:500 500
原始类型:16
最小值imgA:99
imgA中的最大val:255
原始图像大小:500 500
原始类型:16
最小val in imgB:0
最大val in imgB:255

opengl support available产品中的
最小值:0
产品中的最大值:255


b $ b

我认为产品中的最大值必须大于255,但是被截断为255,因为两个矩阵的类型为16.
我试图将矩阵转换为CV_32F,但是产品中的maxVal为64009(我不明白的数字)

感谢 Wajih 评论我做了一些基本的测试,和一些基本的调试,我得到我的工作完美。我认为这可能成为一个关于alpha混合和图像倍增的迷你教程,但现在只有几行注释代码。



请注意,2张图片必须是相同的大小..并肯定一些错误检查应该为固体代码。



希望它帮助别人!当然,如果你有一些提示,使这个代码更可读或更紧凑(一线人都非常感谢!)或高效..只是评论,谢谢你!

  #include< opencv2 / core / core.hpp> 
#include< opencv2 / highgui / highgui.hpp>
#includeopencv2 / 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<<<<<必须具有用于调用minMaxLoc的1个频道< endl;
}

minMaxLoc(m,& minVal,& maxVal,& minLoc,& maxLoc);
cout<< min val in<名称<< :<< minVal < in loc:< minLoc < endl;
cout<< max val in<名称<< :<< 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;
垫产品;

//快速矩阵创建,逗号分隔初始化器
//示例1:创建一个值为0到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;

//不是,如果值超过255,则它在值%256处被截断
imgA =(Mat_ (3,3)<< 3,4,5,6,7,255);
cout<< test Mat 3x3 with last element truncated to 258%256 = 2< endl imgA < endl;

//创建第二个矩阵
imgB = Mat(3,3,CV_8UC1);
imgB =(Mat_< uchar>(3,3)<<< 0,1,2,3,4,5,6,7,8);

//现在的矩阵乘积。我们将值从0-255乘以另一个0-255值。
//边缘情况是min * min和max * max,
//表示:我们的产品是一个函数,返回一个值在域0 * 0-255 * 255; 0-65025
//啊,啊!这个数字超过Mat U8C1域!我们需要不同的数据类型。
//我们需要一个更大的一个..我们说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);

//转换后的值是否被缩放?
cout<< 转化后的imgA:< endl imgA_32FC1<< endl;
cout<< 转换后的imgB:< endl imgB_32FC1<< endl;

product = imgA_32FC1.mul(imgB_32FC1);
//注意:产品值在范围0-65025
cout<< 产品:< endl产品< endl;

//现在,这没有什么意义,因为我们从0-255范围Mat开始,现在我们有一个0-65025没什么..
//它是不是uchar范围,它不是浮动范围(这是大得多)
//所以,我们可以规范化回到0-255
//什么意思与'normalize'现在?
// i表示:将所有值映射为0到0和65025到255的常量。
product.convertTo(product,CV_32FC1,1.0f / 65025.0f * 255);
//但它仍然是一个32FC1 ..不是作为开始matix ..
cout<< 产品,归一化回0-255,仍然在32FC1:< endl产品< endl;
product.convertTo(product,CV_8UC1);
cout<< 该乘积,归一化为0-255,现在为int 8UC1:< endl产品< endl;

cout<< ------------------------------------------------- ----------<< endl;

//现在真正的东西。
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);

//在一个大图像中合并两个图像
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;
}


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 code:

#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;
}

here is the result:

OpenCV version: 2 4
original image size: 500 500
original type: 16
min val in imgA: 99
max val in imgA: 255
original image size: 500 500
original type: 16
min val in imgB: 0
max val in imgB: 255
init done 
opengl support available 
min val in product: 0
max val in product: 255

I think that max value in the product has to be greater than 255, but is truncated to 255 because the type of the two matrixes is 16. I have tried to convert the matrixes to CV_32F but the maxVal in the product is 64009 (a number that i don't understand)

解决方案

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

这篇关于opencv - 图像乘法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆