本文介绍了opencv - 图像乘法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我想和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 cout<< max val in<< s } 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 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 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 //不是,如果值超过255,则它在值%256处被截断 imgA =(Mat_ (3,3) cout<< test Mat 3x3 with last element truncated to 258%256 = 2< endl imgA //创建第二个矩阵 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 4original image size: 500 500original type: 16min val in imgA: 99max val in imgA: 255original image size: 500 500original type: 16min val in imgB: 0max val in imgB: 255init doneopengl support availablemin val in product: 0max val in product: 255I 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 - 图像乘法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 05-25 22:35