OpenCV 色调曲线编程
OpenCV Tone Curve progrommatically
我想实现色调曲线之类的东西
我已经预定义了一组应用于图像的曲线。
例如:
据我了解,在这张图表上我们看到了当前音调值对新音调值的依赖性,例如:
如果我们得到左边的第一个点 - 每个 = 0 的 r、g 和 b 都将转换为 64
或每个大于 224 的值将被转换为 0 等。
所以我尝试将图像的每个像素更改为新值
出于测试目的,我简化了曲线:
这里是我的代码:
//init original image
cv::Mat originalMat = [self cvMatFromUIImage:inputImage];
//out image the same size
cv::Mat outMat = [self cvMatFromUIImage:inputImage];
//loop throw every row of image
for( int y = 0; y < originalMat.rows; y++ ){
//loop throw every column of image
for( int x = 0; x < originalMat.cols; x++ ){
//loop throw every color channel of image (R,G,B)
for( int c = 0; c < 3; c++ ){
if(originalMat.at<cv::Vec3b>(y,x)[c] <= 64)
outMat.at<cv::Vec3b>(y,x)[c] = 64 + ( originalMat.at<cv::Vec3b>(y,x)[c] ) -
( originalMat.at<cv::Vec3b>(y,x)[c] ) * 2 ;
if((originalMat.at<cv::Vec3b>(y,x)[c] > 64)&&(originalMat.at<cv::Vec3b>(y,x)[c] <= 128))
outMat.at<cv::Vec3b>(y,x)[c] = (( originalMat.at<cv::Vec3b>(y,x)[c] ) - 64 ) * 4
;
if((originalMat.at<cv::Vec3b>(y,x)[c] > 128))
outMat.at<cv::Vec3b>(y,x)[c] = ( originalMat.at<cv::Vec3b>(y,x)[c] ) + 128 -
(( originalMat.at<cv::Vec3b>(y,x)[c] ) - 128) * 3;
} //end of r,g,b loop
} //end of column loop
} //end of row loop
//send to output
return [self UIImageFromCVMat:outMat];
但我得到的结果是:
由于某种原因只处理了 3/4 的图像
它与我预期的结果不匹配:
更新0
感谢 @ACCurrent 评论发现计算错误(代码和图像已更新),但仍然不明白为什么只处理了 3/4 的图像。
不太明白为什么会出现'noise',希望是因为曲线不平滑。
寻找避免.at
操作的方法。
更新 1
原图:
您需要使用 Vec4b
访问图像
originalMat.type() is equals to 24
您的 originalMat
是 24 类型,即 CV_8UC4
。这意味着该图像有 4 个通道,但您使用 Vec3b
访问它就好像它只有 3 个通道一样。这就解释了为什么大约 1/4 的图像没有被修改。
因此,只需将代码中的每个 Vec3b
替换为 Vec4b
。
我想实现色调曲线之类的东西
我已经预定义了一组应用于图像的曲线。
例如:
据我了解,在这张图表上我们看到了当前音调值对新音调值的依赖性,例如: 如果我们得到左边的第一个点 - 每个 = 0 的 r、g 和 b 都将转换为 64 或每个大于 224 的值将被转换为 0 等。
所以我尝试将图像的每个像素更改为新值
出于测试目的,我简化了曲线:
这里是我的代码:
//init original image
cv::Mat originalMat = [self cvMatFromUIImage:inputImage];
//out image the same size
cv::Mat outMat = [self cvMatFromUIImage:inputImage];
//loop throw every row of image
for( int y = 0; y < originalMat.rows; y++ ){
//loop throw every column of image
for( int x = 0; x < originalMat.cols; x++ ){
//loop throw every color channel of image (R,G,B)
for( int c = 0; c < 3; c++ ){
if(originalMat.at<cv::Vec3b>(y,x)[c] <= 64)
outMat.at<cv::Vec3b>(y,x)[c] = 64 + ( originalMat.at<cv::Vec3b>(y,x)[c] ) -
( originalMat.at<cv::Vec3b>(y,x)[c] ) * 2 ;
if((originalMat.at<cv::Vec3b>(y,x)[c] > 64)&&(originalMat.at<cv::Vec3b>(y,x)[c] <= 128))
outMat.at<cv::Vec3b>(y,x)[c] = (( originalMat.at<cv::Vec3b>(y,x)[c] ) - 64 ) * 4
;
if((originalMat.at<cv::Vec3b>(y,x)[c] > 128))
outMat.at<cv::Vec3b>(y,x)[c] = ( originalMat.at<cv::Vec3b>(y,x)[c] ) + 128 -
(( originalMat.at<cv::Vec3b>(y,x)[c] ) - 128) * 3;
} //end of r,g,b loop
} //end of column loop
} //end of row loop
//send to output
return [self UIImageFromCVMat:outMat];
但我得到的结果是:
由于某种原因只处理了 3/4 的图像
它与我预期的结果不匹配:
更新0
感谢 @ACCurrent 评论发现计算错误(代码和图像已更新),但仍然不明白为什么只处理了 3/4 的图像。
不太明白为什么会出现'noise',希望是因为曲线不平滑。
寻找避免.at
操作的方法。
更新 1
原图:
您需要使用 Vec4b
originalMat.type() is equals to 24
您的 originalMat
是 24 类型,即 CV_8UC4
。这意味着该图像有 4 个通道,但您使用 Vec3b
访问它就好像它只有 3 个通道一样。这就解释了为什么大约 1/4 的图像没有被修改。
因此,只需将代码中的每个 Vec3b
替换为 Vec4b
。