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

2023-09-18 18:32:50

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

1、为什么对图像像素类型转换与归一化
  • 数据一致性:不同的图像可能使用不同的像素类型来表示图像数据,如8位无符号整数、16位无符号整数、32位浮点数等。在某些情况下,为了进行后续处理或者与其他图像进行比较,需要确保所有图像使用相同的数据类型,因此需要进行像素类型转换,以使它们的数据类型一致。
  • 算法需求:某些图像处理算法对输入图像的数据类型有特定的要求。例如,某些滤波器或变换可能需要输入为浮点数图像,因此需要将图像像素类型从整数转换为浮点数。
  • 增强对比度:归一化是将像素值映射到特定范围内,通常是[0, 1]或[0, 255]。这可以用来增强图像的对比度,使亮度范围更易于可视化或用于后续处理。
  • 避免溢出和截断:在进行一些图像操作时,像素值可能会超出特定范围(如255对于8位无符号整数图像)。归一化可以确保像素值在有效范围内,避免溢出或截断。
  • 数据处理和机器学习:在机器学习和深度学习中,通常需要将输入数据进行标准化或归一化,以便模型的训练和性能更好。图像像素值的归一化可以是这个过程的一部分。
  • 显示和可视化:有时候,将图像像素值归一化到合适的范围可以更好地显示图像或将其可视化,使图像更容易理解和分析。
2、在OpenCV中,convertTo()normalize() 是两个常用的图像处理函数,用于图像像素类型转换和归一化;
  • 图像的像素类型就是cv::Mat元素的数据类型
  • cv::Mat的元素类型决定了它可以存储的数据的种类,比如8位无符号整数(CV_8U)、16位无符号整数(CV_16U)、32位浮点数(CV_32F)等等。不同的元素类型决定了图像的颜色深度、精度以及可以表达的范围。
(1)convertTo() 函数用于将一个 cv::Mat 对象的像素类型转换为另一种类型。它的基本用法如下:
void cv::Mat::convertTo(
    OutputArray m,
    int rtype,
    double alpha = 1,
    double beta = 0
) const;

参数解释:
m:输出的目标图像;
rtype:目标图像的数据类型(可以使用 OpenCV 提供的常量如CV_8U、CV_16U、CV_32F等);
alpha:缩放因子,用于线性变换。默认为1; 
beta:偏移量,用于线性变换。默认为0

示例:

cv::Mat img = cv::imread("input.jpg");
cv::Mat new_img;
img.convertTo(new_img, CV_32F); // 将图像转换为32位浮点数类型
(2)normalize() 函数用于将图像的像素值归一化到指定的范围内,通常是 [0, 1] 或 [0, 255]。
void cv::normalize(
    InputArray src,  
    OutputArray dst,   
    double alpha = 0,  
    double beta = 255,    
    int norm_type = NORM_L2,   
    int dtype = -1,           
    InputArray mask = noArray()   
);

参数解释:
src:输入图像;
dst:输出归一化后的图像;
alpha:归一化的下界; 
beta:归一化的上界; 
norm_type:归一化类型,默认为NORM_L2(
	NORM_MINMAX
	NORM_INF
	NORM_L1
	NORM_L2
)
dtype:输出图像的数据类型(默认值-1,如果为负数,将使用输入图像的数据类型) ;
mask:掩码,可选参数; 

示例:

cv::Mat img = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat normalized_img;
cv::normalize(img, normalized_img, 0, 255, cv::NORM_MINMAX, CV_8U);

在这个示例中,normalize() 函数将图像的像素值归一化到 [0, 255] 的范围内,并将结果保存在 normalized_img 中。

总的来说,convertTo() 用于更改图像的数据类型,而 normalize() 用于将像素值归一化到指定范围内。这两个函数在图像处理中经常会用到,可以根据具体的需求来选择使用。

3、代码实例说明:
(1)图像像素类型转换:
#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 读取图像
    cv::Mat img = cv::imread("input.jpg");

    if (img.empty()) {
        std::cerr << "Could not read the image." << std::endl;
        return -1;
    }
    // 转换前的像素数据类型CV_8UC3
    std::cout << img.type() << std::endl;
    // 将图像从当前类型转换为新的类型CV_32FC3
    cv::Mat new_img;
    img.convertTo(new_img, CV_32F); // 这里将图像转换为32位浮点数类型,可以使用 CV_8U、CV_16U、CV_32F 等来选择不同的目标类型
    // 转换后的像素数据类型
    std::cout << new_img.type() << std::endl;

    // 进一步处理 new_img ...

    return 0;
}

(2)图像归一化:将图像像素的值映射到一个特定的范围内,通常是[0, 1]或者[0, 255]。
convertTo() 函数

将像素值归一化到[0, 1]范围:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 读取灰度图像
    cv::Mat img = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);

    if (img.empty()) {
        std::cerr << "Could not read the image." << std::endl;
        return -1;
    }

    // 将像素值转换为浮点数类型并归一化
    cv::Mat normalized_img;
    img.convertTo(normalized_img, CV_32F);
    normalized_img /= 255.0;

    // 进一步处理 normalized_img ...

    return 0;
}

将像素值归一化到[0, 255]范围:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 读取灰度图像
    cv::Mat img = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);

    if (img.empty()) {
        std::cerr << "Could not read the image." << std::endl;
        return -1;
    }

    // 将像素值转换为整数类型并归一化
    cv::Mat normalized_img;
    img.convertTo(normalized_img, CV_8U);
    normalized_img *= 255;

    // 进一步处理 normalized_img ...

    return 0;
}

normalize() 函数

将像素值归一化到[0, 1]范围:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 读取灰度图像
    cv::Mat img = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);

    if (img.empty()) {
        std::cerr << "Could not read the image." << std::endl;
        return -1;
    }

    // 将像素值转换为浮点数类型并归一化
    cv::Mat normalized_img;
    cv::normalize(img, normalized_img, 0.0, 1.0, cv::NORM_MINMAX, CV_32F);

    // 进一步处理 normalized_img ...

    return 0;
}

将像素值归一化到[0, 255]范围:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 读取灰度图像
    cv::Mat img = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);

    if (img.empty()) {
        std::cerr << "Could not read the image." << std::endl;
        return -1;
    }

    // 将像素值归一化到[0, 255]范围
    cv::Mat normalized_img;
    cv::normalize(img, normalized_img, 0, 255, cv::NORM_MINMAX, CV_8U);

    // 进一步处理 normalized_img ...

    return 0;
}

convertTo()normalize() 这两个函数都可以用来对图像进行归一化,但它们的具体用途略有不同:

  • convertTo() 函数用于将一个 cv::Mat 对象的像素类型转换为另一种类型,它可以用于进行不同类型之间的转换,包括归一化。例如,可以将图像从8位无符号整数转换为32位浮点数类型,也可以将像素值映射到特定范围内。
  • normalize() 函数专门用于将图像的像素值归一化到指定的范围内,通常是 [0, 1] 或 [0, 255]。这是一种特定于归一化的函数,通常用于数据预处理等情况。

两者可以根据实际需要来选择使用,但请注意它们的不同用途和参数。如果你只需要进行简单的归一化操作,那么 normalize() 可能更为直观和方便。如果需要进行更复杂的类型转换,包括将图像从一种类型转换为另一种类型,那么 convertTo() 可能更为适合。

更多推荐

设计模式:状态模式(C++实现)

状态模式(StatePattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为。状态模式将对象的行为封装在不同的状态类中,使得状态的切换对于对象来说是透明的。下面是一个简单的C++状态模式的示例:#include<iostream>//抽象状态类classState{public:virtualvoidh

Flink--4、DateStream API(执行环境、源算子、基本转换算子)

星光下的赶路人star的个人主页注意力的集中,意象的孤立绝缘,便是美感的态度的最大特点文章目录1、DataStreamAPI1.1执行环境(ExecutionEnvironment)1.1.1创建执行环境1.2执行模式(ExecutionMode)1.3触发程序执行2、源算子(Source)2.1准备工作2.2从集合中

二叉树(相关术语、创建、遍历、最大深度问题)梳理总结

🍓简介:java系列技术分享(👉持续更新中…🔥)🍓初衷:一起学习、一起进步、坚持不懈🍓如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏🍓希望这篇文章对你有所帮助,欢迎点赞👍收藏⭐留言📝🍓更多文章请点击文章目录一、二叉树1.1树的基本定义1.2树的相关术语1.3二叉树的基本定义1.4二叉查找树

OZON测评自养号技巧,提升店铺权重和销量,避免恶意跟卖

在中国的跨境商家眼中,OZON可能是一个陌生的名字,但在俄罗斯人眼中,它是一个家喻户晓的电商平台。自2016年开始在俄罗斯运营以来,OZON已经成为俄罗斯市场上备受欢迎的电商平台,为俄罗斯人提供了丰富多样的产品选择和便利的购物体验。迄今为止,OZON在俄罗斯市场的占有率已经超过了最早深耕俄系市场的速卖通。有市场的地方就

浅谈SpringMVC的请求流程

目录标题浅谈SpringMVC的请求流程SpringMVC的介绍SpringMVC的逻辑概念运行图解知识总结浅谈SpringMVC的请求流程对于SpringMVC而言重点是了解它的底层运行逻辑,从而可以根据其逻辑来进行实际业务的操作或者是利用原理增强业务的功能性,最终达到项目预期效果。SpringMVC的介绍Sprin

【数据库索引优化】

文章目录数据库索引优化1.选择合适的字段创建索引2.限值每张表上的索引数量3.被频繁更新的字段应该慎重建立索引4.尽可能考虑简历联合索引而不是单列索引5.避免冗余索引6.字符串类型的字段使用前缀索引代替普通索引7.避免索引失效8.删除长期未使用的索引数据库索引优化1.选择合适的字段创建索引不为NULL的字段:索引字段的

Postman应用——Variable变量使用(Global、Environment和Collection)

文章目录变量的使用同名变量优先级Postman内置变量Global、Environment和Collection变量设置,点击查看。变量的使用语法:{{变量名}}使用{{}}包裹变量名,引用设置好的变量。注意:Environment变量引用前需要先选择已有的环境,默认不选择任何环境,否则Environment变量不生效

动态码收款与扫码支付:深入剖析

随着移动支付的普及,越来越多的支付方式在我们的生活中出现,其中,动态码收款和扫码支付是两种常见的支付方式。本文将深入剖析这两种方式的差异,并探讨它们各自的优点和缺点。动态码收款,顾名思义,是指收款方提供一个动态生成的二维码,支付方扫描这个二维码进行支付。这种方式的主要优点是安全性高,因为每次交易的二维码都是唯一的,不易

热文推荐