初识 OpenCV 之线性混合,亮度与对比度,各种混合
觉得Opencv越来越好玩了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
图像的变换可以分成两种
1 - 像素变换 – 点操作
2- 邻域操作 – 区域
其中调整图像亮度和对比度属于像素变换-点操作
上次调整亮度用的是掩膜也同样是点操作
f(i,j)代表每一个像素点,alpha一般叫做增益参数,表征对比度,而beta成为偏置参数,表征亮度变化。
Mat des1 = Mat::zeros(src.size(),src.type());
int count = des1.channels();
int weight = des1.rows;
int hight = des1.cols;
float a = 1.2;
float b1 = 30;
Mat m1;
src.convertTo(m1,CV_32F);//把src 转换成32位的float 的m1,提高精度
for (int row = 0; row < hight; row++)
{
for (int col = 0; col < weight; col++)
{
float b = m1.at<Vec3f>(row, col)[0];//at<Vec3f>取出像素点的值
float g = m1.at<Vec3f>(row, col)[1];
float r = m1.at<Vec3f>(row, col)[2];
des1.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*a+b1);//saturate_cast<uchar> 确保0-255
des1.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*a+b1);
des1.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*a+b1);
}
}
图像线性混合的数学原理
取出每一个像素点进行操作,然后进行加权混合
G(x)=(1-alpha)F(x)+alphaQ(x) 1 > alpha > 0
主要代码:
for (int row = 0; row < m1.rows; row++)
{
for (int col = 0; col < m1.cols; col++)
{
float b = m1.at<Vec3b>(row, col)[0];
float g = m1.at<Vec3b>(row, col)[1];
float r = m1.at<Vec3b>(row, col)[2];
float b1 = m2.at<Vec3b>(row, col)[0];
float g1 = m2.at<Vec3b>(row, col)[1];
float r1 = m2.at<Vec3b>(row, col)[2];
m3.at<Vec3b>(row, col)[0] = b*alpha + (1 - alpha)*b1;
m3.at<Vec3b>(row, col)[1] = g*alpha + (1 - alpha)*g1;
m3.at<Vec3b>(row, col)[2] = r*alpha + (1 - alpha)*r1;
}
}
还可以使用addWeighted()
@note Saturation is not applied when the output array has the depth CV_32S. You may even get
result of an incorrect sign in the case of overflow.
@param src1 first input array.
@param alpha weight of the first array elements.
@param src2 second input array of the same size and channel number as src1.
@param beta weight of the second array elements.
@param gamma scalar added to each sum.
@param dst output array that has the same size and number of channels as the input arrays.
@param dtype optional depth of the output array; when both input arrays have the same depth, dtype
can be set to -1, which will be equivalent to src1.depth().
@sa add, subtract, scaleAdd, Mat::convertTo
*/
CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2,
double beta, double gamma, OutputArray dst, int dtype = -1);
addWeighted(m1, alpha, m2, (1 - alpha), 0, m4, -1);
左边的就是addWeight
可以使用add()
@note Saturation is not applied when the output array has the depth CV_32S. You may even get
result of an incorrect sign in the case of overflow.
@param src1 first input array or a scalar.
@param src2 second input array or a scalar.
@param dst output array that has the same size and number of channels as the input array(s); the
depth is defined by dtype or src1/src2.
@param mask optional operation mask - 8-bit single channel array, that specifies elements of the
output array to be changed.
@param dtype optional depth of the output array (see the discussion below).
@sa subtract, addWeighted, scaleAdd, Mat::convertTo
*/
CV_EXPORTS_W void add(InputArray src1, InputArray src2, OutputArray dst,
InputArray mask = noArray(), int dtype = -1);
也可以使用subtract()
@note Saturation is not applied when the output array has the depth CV_32S. You may even get
result of an incorrect sign in the case of overflow.
@param src1 first input array or a scalar.
@param src2 second input array or a scalar.
@param dst output array of the same size and the same number of channels as the input array.
@param mask optional operation mask; this is an 8-bit single channel array that specifies elements
of the output array to be changed.
@param dtype optional depth of the output array
@sa add, addWeighted, scaleAdd, Mat::convertTo
*/
CV_EXPORTS_W void subtract(InputArray src1, InputArray src2, OutputArray dst,
InputArray mask = noArray(), int dtype = -1);
multiply()
@note Saturation is not applied when the output array has the depth
CV_32S. You may even get result of an incorrect sign in the case of
overflow.
@param src1 first input array.
@param src2 second input array of the same size and the same type as src1.
@param dst output array of the same size and type as src1.
@param scale optional scale factor.
@param dtype optional depth of the output array
@sa add, subtract, divide, scaleAdd, addWeighted, accumulate, accumulateProduct, accumulateSquare,
Mat::convertTo
*/
CV_EXPORTS_W void multiply(InputArray src1, InputArray src2,
OutputArray dst, double scale = 1, int dtype = -1);
divide()
@note Saturation is not applied when the output array has the depth CV_32S. You may even get
result of an incorrect sign in the case of overflow.
@param src1 first input array.
@param src2 second input array of the same size and type as src1.
@param scale scalar factor.
@param dst output array of the same size and type as src2.
@param dtype optional depth of the output array; if -1, dst will have depth src2.depth(), but in
case of an array-by-array division, you can only pass -1 when src1.depth()==src2.depth().
@sa multiply, add, subtract
*/
CV_EXPORTS_W void divide(InputArray src1, InputArray src2, OutputArray dst,
double scale = 1, int dtype = -1);