opencv - 图像乘法 [英] opencv - image multiplication
问题描述
我想和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屋!