opencv Mat数据 乘以系数

需要 Mat 数据乘以一个系数  

  cout << "Bgain: " << Bgain << endl;
  cout << "Ggain: " << Ggain << endl;
  cout << "Rgain: " << Rgain << endl;



一、 常数变同型矩阵,采用 Mat::multiply 函数 进行矩阵运算。

需要注意的2个问题:

1、如果常数是浮点型,那么定义同型矩阵时候,要定义成CV_32FC1的格式,否则会变成 取整处理后的同型矩阵;

2、采用Mat::multiply函数进行运算时,会发生报错现象,目前未解决。


  Mat BgainMat(B.rows, B.cols, CV_8UC1, Scalar::all(Bgain));
  Mat GgainMat(G.rows, G.cols, CV_8UC1, Scalar::all(Ggain));
  Mat RgainMat(R.rows, R.cols, CV_8UC1, Scalar::all(Rgain));
  Rect re(4180, 1650, 6, 6);
  cout << "BgainMat: " << BgainMat(re) << endl;
  cout << "GgainMat: " << GgainMat(re) << endl;
  cout << "RgainMat: " << RgainMat(re) << endl;


opencv Mat数据 乘以系数_第1张图片


修改Scalar 数值:

  Mat BgainMat(B.rows, B.cols, CV_8UC1, Scalar::all(3.56));
  Mat GgainMat(G.rows, G.cols, CV_8UC1, Scalar::all(1.25));
  Mat RgainMat(R.rows, R.cols, CV_8UC1, Scalar(Rgain));
  Rect re(4180, 1650, 6, 6);
  cout << "BgainMat: " << BgainMat(re) << endl;
  cout << "GgainMat: " << GgainMat(re) << endl;
  cout << "RgainMat: " << RgainMat(re) << endl;

opencv Mat数据 乘以系数_第2张图片


原因: 无论Scalar是什么浮点值,输出的均为四舍五入后的整数型

问题不在输入参数,在于Mat类型的定义  8UC1  


Mat.hpp  源码 :

    int type() const;

    /** @brief Returns the depth of a matrix element.

    The method returns the identifier of the matrix element depth (the type of each individual channel).
    For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of
    matrix types contains the following values:
    -   CV_8U - 8-bit unsigned integers ( 0..255 )
    -   CV_8S - 8-bit signed integers ( -128..127 )
    -   CV_16U - 16-bit unsigned integers ( 0..65535 )
    -   CV_16S - 16-bit signed integers ( -32768..32767 )
    -   CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
    -   CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
    -   CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
     */

opencv Mat数据 乘以系数_第3张图片


矩阵输出问题解决,

但是矩阵运算出现报错

  multiply(B, BgainMat, newB);
  multiply(G, GgainMat, newG);
  multiply(R, RgainMat, newR);

opencv Mat数据 乘以系数_第4张图片

二、 通过 cvConvertScale 函数进行运算。

但是 : 存在一些小问题

  cvConvertScale(B, newB, Ggain,0);

不存在 从 Cv::Mat 到 Cv::Arr *  的适当转换函数

参考博文 : 上篇转载  该博文的解决方案是,针对Mat类型的数据,选用不以cv开头的函数。

cvConvertScale :以cv开头的函数 输入参数列表  矩阵类型 大都为  cv::Arr * 类型      以Mat类型作为输入参数时会报错的  不存在 Mat 到 Arr的适当转换函数

convertMaps :  不带cv的函数  输入参数多为  cv::inputArray  类型  ,    此类函数 输入参数类型  Mat 类型的是可以的。


三、自己写代码,对Mat数据元素进行操作的方式实现:

需要注意存在的问题:当计算结果超出255时,注意处理溢出问题。否则图像结果会发生如下的问题。

  for (int i = 0; i < B.rows;i++){
	  //uchar* dataB = B.ptr(i);
	  //uchar* dataNewB = newB.ptr(i);
	  for (int j = 0; j < B.cols;j++){
		  //dataNewB[j] = dataB[j] * Bgain;  // 指针访问的方式 操作数据元素
		  //dataNewG[j] = dataG[j] * Ggain;
		  //dataNewR[j] = dataR[j] * Rgain;
		  newB.at(i, j) = B.at(i, j) * Bgain; // 动态地址访问方式 操作数据元素
		  newG.at(i, j) = G.at(i, j) * Ggain;
		  newR.at(i, j) = R.at(i, j) * Rgain;
	  }
  }
opencv Mat数据 乘以系数_第5张图片
输出结果显示, newB发生了 数据的溢出。

处理后的图片效果:

opencv Mat数据 乘以系数_第6张图片



四、简洁可行

最后,最后, 发现,Mat矩阵 直接乘以数值就可以了,并且能自动满足溢出时取最大值255的处理。  兜兜转转一大圈,最初曾经这样试过,可能某个地方出问题了,结果绕了一圈,想了很多其它的如前述的方式进行计算,足足花费一天时间。

  newB = B * Bgain;
  newG = G * Ggain;
  newR = R * Rgain;

  cout << "newB: " << newB(re) << endl;
  cout << "newG: " << newG(re) << endl;
  cout << "newR: " << newR(re) << endl;
  cout << "newC: " << newC(re) << endl;

opencv Mat数据 乘以系数_第7张图片






















你可能感兴趣的:(opencv)