/*
txwtech
OpenCV07调整图像的亮度和对比度
图像变换可以看作如下:
- 像素变换 – 点操作
- 邻域操作 – 区域
调整图像亮度和对比度属于像素变换-点操作
g(i,j)=af(i,j)+b,其中a(alpha)>0,b(beta)是增益变量
f(i,j)表示一个像素点
a:对比度
b:亮度,数值越大,亮度越高
API:
Mat new_image = Mat::zeros( image.size(), image.type() );
创建一张跟原图像大小和类型一致的空白图像、像素值初始化为0
saturate_cast<uchar>(value)确保值大小范围为0~255之间
Mat.at<Vec3b>(y,x)[index]=value 给每个像素点每个通道赋值
//float color_b = src.at<Vec3f>(row, col)[0];
//float color_g = src.at<Vec3f>(row, col)[1];
//float color_r = src.at<Vec3f>(row, col)[2];
/*
OpenCV Error: Assertion failed (((((sizeof(size_t)<<28)|0x8442211) >>
((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file
d:\opencv3\opencv\build\include\opencv2\core\mat.inl.hpp, line 919
报错,Mat src的图像是uchar,所以应该是src.at<Vec3b>,如果需要使用src.converTo转换为Vec3f的数据
CV_DbgAssert(CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
convertTo的用法 src.convertTo(dst, type, scale, shift) img参数为图像数据来源,其类型为Mat。
注意也不是所有格式的Mat型数据都能被使用保存为图片,目前OpenCV主要只支持单通道和3通道的图像,
并且此时要求其深度为8bit和16bit无符号(即CV_16U),所以其他一些数据类型是不支持的,比如说float型等。
如果Mat类型数据的深度和通道数不满足上面的要求,则需要使用convertTo()函数和cvtColor()函数来进行转换。
convertTo()函数负责转换数据类型不同的Mat,即可以将类似float型的Mat转换到imwrite()函数能够接受的类型。
而cvtColor()函数是负责转换不同通道的Mat,因为该函数的第4个参数就可以设置目的Mat数据的通道数
(只是我们一般没有用到它,一般情况下这个函数是用来进行色彩空间转换的)。
另外也可以不用imwrite()函数来存图片数据,可以直接用通用的XML IO接口函数将数据存在XML或者YXML中。
缩放并转换到另外一种
数据类型:
dst:目的矩阵;
type:需要的输出矩阵类型,或者更明确的,是输出矩阵的深度,如果是负值(常用-1)则输出矩阵和输入矩阵类型相同;
scale:比例因子;
shift:将输入数组元素按比例缩放后添加的值;
dst(i)=src(i)xscale+(shift,shift,...)
如果scale=1,shift=0,则不进行比例缩放。
如果输入数组与输出数组的类型相同,则函数可以被用于缩放和平移矩阵或图像;
————————————————
在OpenCv中,使用Mat存图像,有专门的数据类型 一般的图像文件格式使用的是 Unsigned 8bits吧,CvMat矩阵对应的参数类型就是 CV_8UC1,CV_8UC2,CV_8UC3。 其中 U代表 Unsigned 无符号、C代表CvMat 后面的数字代表通道数 (最后的1、2、3表示通道数,譬如RGB3通道就用CV_8UC3)
而float 是32位的,对应CvMat数据结构参数就是:CV_32FC1,CV_32FC2,CV_32FC3... double是64bits,对应CvMat数据结构参数:CV_64FC1,CV_64FC2,CV_64FC3等。
7.OpenCV 源代码中的定义: typedef Vec <uchar, 2> Vec2b; Vec2b—表示每个Vec2b对象中,可以存储2个char(字符型)数据 Vec3b—表示每一个Vec3b对象中,可以存储3个char(字符型)数据,比如可以用这样的对象,去存储RGB图像中的 Vec4b—表示每一个Vec4b对象中,可以存储4个字符型数据,可以用这样的类对象去存储—4通道RGB+Alpha的图
遍历方法就是 用 at 其中现需要 把模板类T 变成Vec4b
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
//Mat::at()取值或改变某点的像素值比较耗时,可以采用Mat的模板子类Mat_<T>
//Mat类中的at方法作用:用于获取图像矩阵某点的值或改变某点的值。
double temp = img.at<Vec4b>(i, j)[3] / 255.0;
mat.at<Vec4b>(i, j)[0] = (1 - temp)*back_img.at<Vec4b>(i, j)[0] + temp *img.at<Vec4b>(i, j)[0];
mat.at<Vec4b>(i, j)[1] = (1 - temp)*back_img.at<Vec4b>(i, j)[1] + temp *img.at<Vec4b>(i, j)[1];
mat.at<Vec4b>(i, j)[2] = (1 - temp)*back_img.at<Vec4b>(i, j)[2] + temp *img.at<Vec4b>(i, j)[2];
mat.at<Vec4b>(i, j)[3] = (1 - temp)*back_img.at<Vec4b>(i, j)[3] + temp *img.at<Vec4b>(i, j)[3];
}
}
*/
/*
txwtech
OpenCV07调整图像的亮度和对比度
图像变换可以看作如下:
- 像素变换 – 点操作
- 邻域操作 – 区域
调整图像亮度和对比度属于像素变换-点操作
g(i,j)=af(i,j)+b,其中a(alpha)>0,b(beta)是增益变量
f(i,j)表示一个像素点
a:对比度
b:亮度,数值越大,亮度越高
API:
Mat new_image = Mat::zeros( image.size(), image.type() );
创建一张跟原图像大小和类型一致的空白图像、像素值初始化为0
saturate_cast<uchar>(value)确保值大小范围为0~255之间
Mat.at<Vec3b>(y,x)[index]=value 给每个像素点每个通道赋值
//float color_b = src.at<Vec3f>(row, col)[0];
//float color_g = src.at<Vec3f>(row, col)[1];
//float color_r = src.at<Vec3f>(row, col)[2];
/*
OpenCV Error: Assertion failed (((((sizeof(size_t)<<28)|0x8442211) >>
((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file
d:\opencv3\opencv\build\include\opencv2\core\mat.inl.hpp, line 919
报错,Mat src的图像是uchar,所以应该是src.at<Vec3b>,如果需要使用src.converTo转换为Vec3f的数据
CV_DbgAssert(CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
convertTo的用法 src.convertTo(dst, type, scale, shift) img参数为图像数据来源,其类型为Mat。
注意也不是所有格式的Mat型数据都能被使用保存为图片,目前OpenCV主要只支持单通道和3通道的图像,
并且此时要求其深度为8bit和16bit无符号(即CV_16U),所以其他一些数据类型是不支持的,比如说float型等。
如果Mat类型数据的深度和通道数不满足上面的要求,则需要使用convertTo()函数和cvtColor()函数来进行转换。
convertTo()函数负责转换数据类型不同的Mat,即可以将类似float型的Mat转换到imwrite()函数能够接受的类型。
而cvtColor()函数是负责转换不同通道的Mat,因为该函数的第4个参数就可以设置目的Mat数据的通道数
(只是我们一般没有用到它,一般情况下这个函数是用来进行色彩空间转换的)。
另外也可以不用imwrite()函数来存图片数据,可以直接用通用的XML IO接口函数将数据存在XML或者YXML中。
缩放并转换到另外一种
数据类型:
dst:目的矩阵;
type:需要的输出矩阵类型,或者更明确的,是输出矩阵的深度,如果是负值(常用-1)则输出矩阵和输入矩阵类型相同;
scale:比例因子;
shift:将输入数组元素按比例缩放后添加的值;
dst(i)=src(i)xscale+(shift,shift,...)
如果scale=1,shift=0,则不进行比例缩放。
如果输入数组与输出数组的类型相同,则函数可以被用于缩放和平移矩阵或图像;
————————————————
在OpenCv中,使用Mat存图像,有专门的数据类型 一般的图像文件格式使用的是 Unsigned 8bits吧,CvMat矩阵对应的参数类型就是 CV_8UC1,CV_8UC2,CV_8UC3。 其中 U代表 Unsigned 无符号、C代表CvMat 后面的数字代表通道数 (最后的1、2、3表示通道数,譬如RGB3通道就用CV_8UC3)
而float 是32位的,对应CvMat数据结构参数就是:CV_32FC1,CV_32FC2,CV_32FC3... double是64bits,对应CvMat数据结构参数:CV_64FC1,CV_64FC2,CV_64FC3等。
7.OpenCV 源代码中的定义: typedef Vec <uchar, 2> Vec2b; Vec2b—表示每个Vec2b对象中,可以存储2个char(字符型)数据 Vec3b—表示每一个Vec3b对象中,可以存储3个char(字符型)数据,比如可以用这样的对象,去存储RGB图像中的 Vec4b—表示每一个Vec4b对象中,可以存储4个字符型数据,可以用这样的类对象去存储—4通道RGB+Alpha的图
遍历方法就是 用 at 其中现需要 把模板类T 变成Vec4b
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
//Mat::at()取值或改变某点的像素值比较耗时,可以采用Mat的模板子类Mat_<T>
//Mat类中的at方法作用:用于获取图像矩阵某点的值或改变某点的值。
double temp = img.at<Vec4b>(i, j)[3] / 255.0;
mat.at<Vec4b>(i, j)[0] = (1 - temp)*back_img.at<Vec4b>(i, j)[0] + temp *img.at<Vec4b>(i, j)[0];
mat.at<Vec4b>(i, j)[1] = (1 - temp)*back_img.at<Vec4b>(i, j)[1] + temp *img.at<Vec4b>(i, j)[1];
mat.at<Vec4b>(i, j)[2] = (1 - temp)*back_img.at<Vec4b>(i, j)[2] + temp *img.at<Vec4b>(i, j)[2];
mat.at<Vec4b>(i, j)[3] = (1 - temp)*back_img.at<Vec4b>(i, j)[3] + temp *img.at<Vec4b>(i, j)[3];
}
}
*/
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
int main(int argc, char * argv[])
{
Mat src;
Mat src_Vec3f;
Mat dst2;
src = imread("E:/pictures/test1.jpg");
if (!src.data)
{
printf("failed to load img");
return -1;
}
char source_window[] = "source_img";
namedWindow(source_window,CV_WINDOW_AUTOSIZE);
imshow(source_window,src);
//vector<int> veci;
//veci.push_back(1);
int height = src.rows;
int width = src.cols;
dst2 = Mat::zeros(src.size(),src.type());
float alpha = 1.2;//对比度
float beta = 30;//增强的亮度
src.convertTo(src_Vec3f,CV_32F,1.0,0.0);//uchar转换成float
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
if(src.channels()==3)
{
//float color_b = src.at<Vec3f>(row, col)[0];
//float color_g = src.at<Vec3f>(row, col)[1];
//float color_r = src.at<Vec3f>(row, col)[2];
/*
OpenCV Error: Assertion failed (((((sizeof(size_t)<<28)|0x8442211) >>
((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file
d:\opencv3\opencv\build\include\opencv2\core\mat.inl.hpp, line 919
报错,Mat src的图像是uchar,所以应该是src.at<Vec3b>,如果需要使用src.converTo转换为Vec3f的数据
CV_DbgAssert(CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
*/
//如下使用方法就是正确的
/*float color_b = src_Vec3f.at<Vec3f>(row, col)[0];
float color_g = src_Vec3f.at<Vec3f>(row, col)[1];
float color_r = src_Vec3f.at<Vec3f>(row, col)[2];*/
float color_b = src.at<Vec3b>(row, col)[0];
float color_g = src.at<Vec3b>(row, col)[1];
float color_r = src.at<Vec3b>(row, col)[2];
dst2.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(color_b*alpha+beta);
dst2.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(color_g*alpha + beta);
dst2.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(color_r*alpha+beta);
}
else if (src.channels() == 1)
{
float v = src.at<uchar>(row,col);
dst2.at<uchar>(row, col) = saturate_cast<uchar>(v*alpha+beta);
}
}
}
char out_caption[] = "saturate and light result";
namedWindow(out_caption,CV_WINDOW_AUTOSIZE);
imshow(out_caption,dst2);
waitKey(0);
return 0;
}