欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > OpenCV 图像像素类型转换与归一化

OpenCV 图像像素类型转换与归一化

2025/6/20 21:06:00 来源:https://blog.csdn.net/weixin_44629261/article/details/148690413  浏览:    关键词:OpenCV 图像像素类型转换与归一化

一、知识点
1、OpenCV支持多种数据类型,每种类型都对应着不同的取值范围。 
  (1)、CV_8U取值范围[0, 255]。
  (2)、CV_16U取值范围[0, 65535]。
  (3)、CV_32F取值范围[0, 1]。
  
2、OpenCV提供convertTo()函数来转换数据类型,提供normalize()函数来改变取值范围。

3、void Mat::convertTo(OutputArray dst, int rtype, double alpha, double beta) const
  (1)、Mat成员函数,将Mat对象转换到另一种数据类型。
  (2)、参数说明:
      dst: 输出数组。
      rtype: 输出数组的期望类型,如CV_8UC1、CV_8UC3、CV_32FC3等。
      alpha: 缩放因子,默认值为1,用于乘以输入矩阵的每个元素。
      beta: 偏移量,默认值为0,用于将缩放后的值加上偏移量。

4、void normalize( InputArray src, 
                  InputOutputArray dst, 
                  double alpha = 1, 
                  double beta = 0,
                  int norm_type = NORM_L2, 
                  int dtype = -1, 
                  InputArray mask = noArray());

  (1)、将数组归一化到指定的取值范围。
  (2)、参数说明:
      src: 输入数组。
      dst: 输出数组,其类型和输入数组相同。
      alpha: 归一化后的最小值或缩放系数,具体取决于norm_type。 若为NORM_MINMAX则表示归一化后的最小值; 若为NORM_INF、NORM_L1、NORM_L2则表示缩放系数。
      beta: 归一化后的最大值,仅当norm_type为NORM_MINMAX时有效。
      norm_type: 归一化的方式,cv::NormTypes枚举值,详见5。
      dtype: 为负数时,dst的类型和src相同; 否则,dst的通道数和src相同,但深度为dtype。
      mask: 可选掩码,若不为空,则在指定数组中(非零掩码对应)归一化; 若为空,则在整个数组归一化。
  (3)、注意,norm_type为NORM_MINMAX时,虽然alpha表示最小值,beta表示最大值,但是两值调换也不影响。
      
5、enum NormTypes {
    NORM_INF = 1,
    NORM_L1 = 2,
    NORM_L2 = 4,
    NORM_L2SQR = 5,
    NORM_HAMMING = 6,
    NORM_HAMMING2 = 7,
    NORM_TYPE_MASK = 7, 
    NORM_RELATIVE = 8, 
    NORM_MINMAX = 32 
};

  (1)、常用NORM_INF、NORM_L1、NORM_L2、NORM_MINMAX这四种归一化方式。
  (2)、NORM_L1,所有像素所有通道的值和为1。
      cv::normalize(src, dst, 1.0, 0.0, cv::NORM_L1);
      sum = 2 + 8 + 10 = 20
      2  --->  0.1   (2.0 / 20.0)
      8  --->  0.4   (8.0 / 20.0)
      10 --->  0.5   (10.0 / 20.0)
  (3)、NORM_L2,所有像素所有通道的值求单位向量。 (默认)
      cv::normalize(src, dst, 1.0, 0.0, cv::NORM_L2);
      |v| = 开根号(2 * 2 + 8 * 8 + 10 * 10) = 开根号(168) = 12.96
      2  --->  0.15   (2.0 / 12.96)
      8  --->  0.62   (8.0 / 12.96)
      10 --->  0.77   (10.0 / 12.96)
  (4)、NORM_INF,每个值除以所有像素所有通道的最大值。
      cv::normalize(src, dst, 1.0, 0.0, cv::NORM_INF);
      Max = 10
      2  --->  0.2   (2.0 / 10.0)
      8  --->  0.8   (8.0 / 10.0)
      10 --->  1.0   (10.0 / 10.0)
  (5)、NORM_MINMAX (常用)
      cv::normalize(src, dst, 0.0, 1.0, cv::NORM_MINMAX);
      alpha = 0.0, beta = 1.0, 归一化范围[0.0, 1.0],简记为[a, b]
      找到样本数据最小值Min = 2, 最大值Max = 10
      计算系数k = (b - a) / (Max - Min) = 1.0 / 8.0 = 0.125
      归一化值 = a + k * (当前值 - Min)
      2  --->  0.0   (0.0 + 0.125 * (2 - 2))
      8  --->  0.75  (0.0 + 0.125 * (8 - 2))
      10 --->  1.0   (0.0 + 0.125 * (10 - 2))
      
6、注意:
  (1)、将CV_8UC3转换为CV_32FC3,8U取值范围[0, 255],32F取值范围[0.0, 1.0],如果不归一化,imshow会显示几乎全白图像。
  (2)、将CV_8UC3图像不转换类型,直接归一化,imshow会显示全黑图片。
  
  
  
二、示例代码

#include <iostream>
#include <opencv2/opencv.hpp>int main()
{//自定义src1,CV_8UC3类型的src1转为CV_32FC3类型的dst1,类型值改变但是元素值不变cv::Mat src1 = cv::Mat::zeros(3, 3, CV_8UC3);src1 = cv::Scalar(45, 60, 80);std::cout << "src1 type = " << src1.type() << std::endl << src1 << std::endl;cv::Mat dst1;src1.convertTo(dst1, CV_32FC3, 1.0, 0.0);std::cout << "dst1 type = " << dst1.type() << std::endl << dst1 << std::endl;//NORM_L1, 所有像素所有通道的值求和为1cv::Mat dst2;cv::normalize(dst1, dst2, 1.0, 0.0, cv::NORM_L1);std::cout << "dst2 type = " << dst2.type() << std::endl << dst2 << std::endl;//NORM_L2, 所有像素所有通道的值求单位向量cv::Mat dst3;cv::normalize(dst1, dst3, 1.0, 0.0, cv::NORM_L2);std::cout << "dst3 type = " << dst3.type() << std::endl << dst3 << std::endl;//NORM_INF, 每个值除以所有像素所有通道的最大值cv::Mat dst4;cv::normalize(dst1, dst4, 1.0, 0.0, cv::NORM_INF);std::cout << "dst4 type = " << dst4.type() << std::endl << dst4 << std::endl;//NORM_MINMAXcv::Mat dst5;cv::normalize(dst1, dst5, 0.0, 1.0, cv::NORM_MINMAX);std::cout << "dst5 type = " << dst5.type() << std::endl << dst5 << std::endl;//src2是读取的图像cv::Mat src2 = cv::imread("../images/6.png");if (src2.empty()){std::cout << "load src2 image error..." << std::endl;return -1;}cv::imshow("原始图像", src2);//CV_8UC3转为32FC3,值没有变化,但是显示会非常白的图片src2.convertTo(src2, CV_32FC3);cv::imshow("类型转换", src2);//NORM_L1,结果值太小,图像显示黑色cv::Mat dst6;cv::normalize(src2, dst6, 1.0, 0.0, cv::NORM_L1);cv::imshow("NORM_L1", dst6);//NORM_L2,结果值太小,放大100倍,图像能显示出来cv::Mat dst7;cv::normalize(src2, dst7, 100.0, 0.0, cv::NORM_L2);cv::imshow("NORM_L2", dst7);//NORM_INFcv::Mat dst8;cv::normalize(src2, dst8, 1.0, 0.0, cv::NORM_INF);cv::imshow("NORM_INF", dst8);//NORM_MINMAXcv::Mat dst9;cv::normalize(src2, dst9, 1.0, 0.0, cv::NORM_MINMAX);cv::imshow("NORM_MINMAX", dst9);//src3和src2读取一样的原始图片, 但如果不转换类型,直接归一化,会显示全黑的图片cv::Mat src3 = cv::imread("../images/6.png");if (src3.empty()){std::cout << "load src3 image error..." << std::endl;return -1;}cv::Mat dst10;cv::normalize(src3, dst10, 1.0, 0.0, cv::NORM_MINMAX);cv::imshow("直接归一化", dst10);cv::waitKey(0);return 0;
}

  输出结果:

src1 type = 16
[ 45,  60,  80,  45,  60,  80,  45,  60,  80;45,  60,  80,  45,  60,  80,  45,  60,  80;45,  60,  80,  45,  60,  80,  45,  60,  80]
dst1 type = 21
[45, 60, 80, 45, 60, 80, 45, 60, 80;45, 60, 80, 45, 60, 80, 45, 60, 80;45, 60, 80, 45, 60, 80, 45, 60, 80]
dst2 type = 21
[0.027027028, 0.036036037, 0.048048049, 0.027027028, 0.036036037, 0.048048049, 0.027027028, 0.036036037, 0.048048049;0.027027028, 0.036036037, 0.048048049, 0.027027028, 0.036036037, 0.048048049, 0.027027028, 0.036036037, 0.048048049;0.027027028, 0.036036037, 0.048048049, 0.027027028, 0.036036037, 0.048048049, 0.027027028, 0.036036037, 0.048048049]
dst3 type = 21
[0.13678823, 0.1823843, 0.24317907, 0.13678823, 0.1823843, 0.24317907, 0.13678823, 0.1823843, 0.24317907;0.13678823, 0.1823843, 0.24317907, 0.13678823, 0.1823843, 0.24317907, 0.13678823, 0.1823843, 0.24317907;0.13678823, 0.1823843, 0.24317907, 0.13678823, 0.1823843, 0.24317907, 0.13678823, 0.1823843, 0.24317907]
dst4 type = 21
[0.5625, 0.75, 1, 0.5625, 0.75, 1, 0.5625, 0.75, 1;0.5625, 0.75, 1, 0.5625, 0.75, 1, 0.5625, 0.75, 1;0.5625, 0.75, 1, 0.5625, 0.75, 1, 0.5625, 0.75, 1]
dst5 type = 21
[2.4214387e-08, 0.42857146, 1, 2.4214387e-08, 0.42857146, 1, 2.4214387e-08, 0.42857146, 1;2.4214387e-08, 0.42857146, 1, 2.4214387e-08, 0.42857146, 1, 2.4214387e-08, 0.42857146, 1;2.4214387e-08, 0.42857146, 1, 2.4214387e-08, 0.42857146, 1, 2.4214387e-08, 0.42857146, 1]

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词