Opencv之.convertTo

本文介绍使用OpenCV库中的convertTo函数快速调整图像对比度和亮度的方法,并通过代码演示了其与传统遍历方法的效率对比。

1.介绍

    对于图像的对比度和亮度的调整,我不多介绍了,这都是基本功,主要是根据公式dst = alpha * src + beta(alpha控制对比度,beta控制亮度)。对于它的实现方法,其实有多种,比如for循环遍历(无上下文依赖关系,可用SSE来优化)、查表法(输出在0-255之间)和本文的猪脚convertTo。

void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;

实现:convertTo实现的功能就是dst = alpha * src + beta

 

2.代码

  1. #include<opencv2\opencv.hpp>

  2. #include<iostream>

  3.  
  4. using namespace std;

  5. using namespace cv;

  6.  
  7. double alpha = 1;

  8. double beta = 50;

  9.  
  10. void changeContrastAndBright(const Mat& src, Mat& dst) {

  11.  
  12. for (int i = 0; i < src.rows; i++)

  13. {

  14. for (int j = 0; j < src.cols; j++)

  15. {

  16. for (int k = 0; k < 3; k++)

  17. {

  18. dst.at<Vec3b>(i, j)[k] =

  19. saturate_cast<uchar>(alpha*(src.at<Vec3b>(i, j)[k]) + beta);

  20. }

  21. }

  22. }

  23.  
  24. }

  25.  
  26.  
  27. int main() {

  28. Mat src = imread("test.png");

  29. Mat dst1;

  30. Mat dst2 = Mat::zeros(src.size(), src.type());

  31.  
  32. double time0 = static_cast<double>(getTickCount());

  33. changeContrastAndBright(src, dst2);

  34. time0 = ((double)getTickCount() - time0) / getTickFrequency();

  35. cout << "直接遍历方法运行时间为:" << time0 << "秒" << endl;

  36.  
  37. time0 = static_cast<double>(getTickCount());

  38. src.convertTo(dst1, src.type(), alpha, beta);

  39. time0 = ((double)getTickCount() - time0) / getTickFrequency();

  40. cout << "convertTo方法运行时间为:" << time0 << "秒" << endl;

  41.  
  42. imshow("src", src);

  43. imshow("dst1", dst1);

  44. imshow("dst2", dst2);

  45. waitKey();

  46. return 0;

  47. }

    Debug和Release下运行,都表明convertTo法比较快

 

3.扩展应用

比如进行反色也是可以的,和这个有得一拼:Opencv之高效函数LUT,建议读者也看看。

<think>我们正在讨论OpenCVSharp中Mat.ConvertTo()方法的使用。用户希望得到一个使用示例。根据OpenCVSharp的文档,ConvertTo()方法用于将矩阵转换为另一种数据类型,并可选择进行缩放。首先,我们要了解ConvertTo()方法的签名。在OpenCVSharp中,它的定义大致如下:publicvoidConvertTo(Matm,intrtype,doublealpha=1,doublebeta=0)参数解释:-m:输出矩阵,将存储转换后的结果。-rtype:期望的输出矩阵类型(例如,MatType.CV_32F表示32位浮点数)。如果为-1,则输出类型与输入相同。-alpha:可选的比例因子(默认值为1)。-beta:可选的偏移量(默认值为0)。该方法执行的操作是:m(x,y)=saturate_cast<rtype>(alpha*(*this)(x,y)+beta)现在,我们提供一个示例。假设我们有一个8位无符号整数类型的Mat(CV_8UC1),我们想将其转换为32位浮点类型(CV_32FC1),并且我们希望将像素值归一化到[0,1]范围。由于原始的8位无符号整数范围是0~255,我们可以设置alpha=1.0/255,beta=0。步骤:1.创建一个源Mat(CV_8UC1类型),并填充一些数据。2.创建一个目标Mat(类型会自动根据rtype确定,但也可以预先创建,不过ConvertTo会重新分配)。3.调用ConvertTo方法。示例代码:```usingOpenCvSharp;classProgram{staticvoidMain(){//创建一个3x3的矩阵,类型为CV_8UC1(8位无符号整数,单通道),并赋初值Matsrc=newMat(3,3,MatType.CV_8UC1,newbyte[]{10,20,30,40,50,60,70,80,90});//创建目标矩阵,也可以不创建,直接在ConvertTo中作为输出参数传递(方法内部会创建或重新分配)Matdst=newMat();//转换到CV_32FC1类型,并缩放至[0,1]范围src.ConvertTo(dst,MatType.CV_32FC1,1.0/255,0);//打印结果Console.WriteLine("源矩阵(CV_8UC1):");Console.WriteLine(src.Dump());Console.WriteLine("目标矩阵(CV_32FC1,归一化到[0,1]):");Console.WriteLine(dst.Dump());}}```输出应该类似于:源矩阵(CV_8UC1):[10,20,30;40,50,60;70,80,90]目标矩阵(CV_32FC1,归一化到[0,1]):[0.039215688,0.078431375,0.11764706;0.15686275,0.19607843,0.23529412;0.27450982,0.3137255,0.3529412]注意:Dump()方法将矩阵内容转换为字符串,方便打印。另外,如果只想改变数据类型而不缩放,可以设置alpha=1,beta=0。有时,我们可能需要将数据类型转换并调整动态范围。例如,将8位无符号整数转换为16位有符号整数,并加上一个偏移量,可以这样:src.ConvertTo(dst,MatType.CV_16SC1,1,-32768);但要注意,这样可能会产生溢出,因为8位无符号整数最大为255,而16位有符号整数范围为[-32768,32767]。上面的操作会将0变成-32768,255变成255-32768=-32513,这显然在范围内,但具体应用需要合理选择alpha和beta。以上是ConvertTo方法的基本使用。§§相关问题§§1.OpenCVSharp中Mat的数据类型有哪些?如何表示?2.除了ConvertTo,还有哪些方法可以改变Mat的数据类型?3.在图像处理中,为什么需要将图像转换为浮点类型?4.在进行矩阵运算时,数据类型转换会带来哪些影响?</think> ### OpenCVSharp `Mat.ConvertTo()`方法详解 `Mat.ConvertTo()`是OpenCVSharp中用于转换矩阵数据类型和值范围的核心方法,其函数签名为: ```csharp public void ConvertTo(OutputArray m, MatType rtype, double alpha = 1, double beta = 0) ``` 参数说明: - `m`:输出矩阵(需预初始化) - `rtype`:目标数据类型(如`MatType.CV_32F`) - `alpha`:比例因子(默认1.0) - `beta`:偏移值(默认0.0) 其执行的计算公式为: $$ \text{dst}(x,y) = \text{saturate\_cast} < \text{目标类型} > (\alpha \times \text{src}(x,y) + \beta) $$ #### 使用示例 ```csharp using OpenCvSharp; // 创建8位无符号整型矩阵(0-255范围) Mat src = new Mat(2, 2, MatType.CV_8UC1, new byte[] { 10, 50, 150, 250 }); // 转换为32位浮点型并归一化到[0,1]范围 Mat dst1 = new Mat(); src.ConvertTo(dst1, MatType.CV_32F, alpha: 1.0/255); // 转换为16位有符号整型(-32678~32767范围) Mat dst2 = new Mat(); src.ConvertTo(dst2, MatType.CV_16SC1, alpha: 256, beta: -32768); // 结果查看 Console.WriteLine($"原始矩阵:\n{src.Dump()}"); Console.WriteLine($"归一化浮点矩阵:\n{dst1.Dump()}"); Console.WriteLine($"16位整型矩阵:\n{dst2.Dump()}"); ``` #### 典型应用场景 1. **图像归一化处理** 将`CV_8U`类型图像转换为`CV_32F`并缩放至[0,1]范围: ```csharp image.ConvertTo(normalized, MatType.CV_32F, 1.0/255); ``` 2. **提高计算精度** 在浮点运算前转换数据类型: ```csharp Mat floatMat = new Mat(); intMat.ConvertTo(floatMat, MatType.CV_32F); ``` 3. **数据范围调整** 将[0,255]映射到[-1,1]: ```csharp image.ConvertTo(output, MatType.CV_32F, alpha: 2.0/255, beta: -1); ``` 4. **深度转换** 16位转8位并保持动态范围: ```csharp ushortImage.ConvertTo(byteImage, MatType.CV_8U, alpha: 255.0/65535); ``` #### 注意事项 1. **预分配输出矩阵** 输出矩阵`m`必须提前初始化(`new Mat()`) 2. **数据溢出处理** 转换时会自动进行饱和截断(saturate_cast)防止溢出 3. **通道数一致性** 输入输出矩阵必须有相同的通道数(可使用`CvtColor()`转换色彩空间) --- ### 相关问题 1. 如何在OpenCVSharp中将16位深度图转换为8位JPEG兼容格式? 2. `ConvertTo()`与`Normalize()`方法在图像处理中有何本质区别? 3. 数据类型转换对OpenCV中的矩阵运算性能有何影响? 4. 如何避免图像数据类型转换过程中的精度损失? 5. 在实时视频处理中如何高效使用`ConvertTo()`方法? > [^1]: OpenCV官方文档 - Matrix Operations > [^2]:《Learning OpenCV 4》第5章 - 矩阵处理技术 > [^3]: OpenCVSharp GitHub源码 - Mat.cs#L1208
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值