OpenCV 图像像素的算术操作

一、知识点
1、operator+

(1)、MatExpr operator + (const Mat & a, const Mat & b);

a、a和b的行数、列数、通道数得相同。

b、a和b的每个像素的每个通道值分别相加。

(2)、MatExpr operator + (const Mat & a, const Scalar & s);

a、若a的通道数和s的标量数相同,则a每个像素的每个通道值和s的每个标量数分别相加。

b、若a的通道数和s的标量数不同,则a每个像素的前几个通道值和s的前几个标量数分别相加。

(3)、MatExpr operator + (const Scalar & s, const Mat & a);

a、若s的标量数和a的通道数相同,则s的每个标量数和a每个像素的每个通道值分别相加。

b、若s的标量数和a的通道数不同,则s的前几个标量数和a每个像素的前几个通道值分别相加。

2、operator-

(1)、MatExpr operator - (const Mat & a, const Mat & b);

a、a和b的行数、列数、通道数得相同。

b、a和b的每个像素的每个通道值分别相减。

(2)、MatExpr operator - (const Mat & a, const Scalar & s);

a、若a的通道数和s的标量数相同,则a每个像素的每个通道值和s的每个标量数分别相减;

b、若a的通道数和s的标量数不同,则a每个像素的前几个通道值和s的前几个标量数分别相减。

(3)、MatExpr operator - (const Scalar & s, const Mat & a);

a、若s的标量数和a的通道数相同,则s的每个标量数和a每个像素的每个通道值分别相减;

b、若s的标量数和a的通道数不同,则s的前几个标量数和a每个像素的前几个通道值分别相减。

3、operator*

(1)、MatExpr operator * (const Mat & a, const Mat & b);

a、a和b矩阵点乘。

b、a的列数和b的行数得相同。

c、a和b的数据类型只能是CV_32FC1、CV_64FC1、CV_32FC2、CV_64FC2中的一种,其它类型如CV_8UC1,编译器会报错。

(2)、MatExpr operator * (const Mat & a, double s);

a、a的每个像素的每个通道值分别和s相乘。

(3)、MatExpr operator * (double s, const Mat & a);

a、s和a的每个像素的每个通道值分别相乘。

4、operator/

(1)、MatExpr operator / (const Mat & a, const Mat & b);

a、a和b的行数、列数、通道数得相同。

b、a和b的每个像素的每个通道值分别相除。

(2)、MatExpr operator / (const Mat & a, double s);

a、a的每个像素的每个通道值除以s。

(3)、MatExpr operator / (double s, const Mat & a);

a、s除以a的每个像素的每个通道值。

5、add()

(1)、void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype = -1);

(2)、参数说明:

src1: 第1个输入数组,通常是Mat对象。

src2: 第2个输入数组,通常是Mat对象。

dst: 输出数组,src1和src2逐元素相加后的结果。

mask: 掩码数组,用于指定哪些元素做加法操作。 默认为noArray(),则对所有元素进行操作。

dtype: 输出数组的数据类型,默认值-1,表示输出数组与输入数组的数据类型相同。

(3)、src1和src2的每个像素的每个通道值都会独立相加,所以src1和src2的行、列、通道数要相同。

6、subtract()

(1)、void subtract(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype = -1);

(2)、参数说明:

src1: 第1个输入数组,通常是Mat对象。

src2: 第2个输入数组,通常是Mat对象。

dst: 输出数组,src1和src2逐元素相减后的结果。

mask: 掩码数组,用于指定哪些元素做减法操作。 默认为noArray(),则对所有元素进行操作。

dtype: 输出数组的数据类型,默认值-1,表示输出数组与输入数组的数据类型相同。

(3)、src1和src2的每个像素的每个通道值都会独立相减,所以src1和src2的行、列、通道数要相同。

7、multiply()

(1)、void multiply(InputArray src1, InputArray src2, OutputArray dst, double scale = 1, int dtype = -1);

(2)、参数说明:

src1: 第1个输入数组,通常是Mat对象。

src2: 第2个输入数组,通常是Mat对象。

dst: 输出数组,src1和src2逐元素相乘后的结果。

scale: 缩放因子,结果会被此因子缩放,默认值1。

dtype: 输出数组的数据类型,默认值-1,表示输出数组与输入数组的数据类型相同。

(3)、src1和src2的每个像素的每个通道值都会独立相乘,所以src1和src2的行、列、通道数要相同。

8、divide()

(1)、void divide(InputArray src1, InputArray src2, OutputArray dst, double scale = 1, int dtype = -1);

(2)、参数说明:

src1: 第1个输入数组,通常是Mat对象。

src2: 第2个输入数组,通常是Mat对象。

dst: 输出数组,src1和src2逐元素相除后的结果。

scale: 缩放因子,结果会被此因子缩放,默认值1。

dtype: 输出数组的数据类型,默认值-1,表示输出数组与输入数组的数据类型相同。

(3)、src1和src2的每个像素的每个通道值都会独立相除,所以src1和src2的行、列、通道数要相同。

9、注意: 有些结果数据因超过数据类型的最大范围,会被截断。 如数据类型8U,则数据300就只能被截断为255。

10、saturate_cast:

(1)、template<typename _Tp>

_Tp saturate_cast(ArgType v);

(2)、将一个值v转换为_Tp类型的值,并确保转换过程中值不会超出_Tp取值范围。

二、示例代码和输出结果:

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>


int main()
{
    cv::Mat m1(3, 3, CV_8UC3, cv::Scalar(20, 40, 30));
    cv::Mat m2(3, 3, CV_8UC3, cv::Scalar(10, 20, 15));
    std::cout << "m1:" << std::endl << m1 << std::endl;
    std::cout << "m2:" << std::endl << m2 << std::endl;
    cv::Mat m3 = cv::Mat::ones(3, 3, CV_32FC1);
    cv::Mat m4 = cv::Mat::ones(3, 3, CV_32FC1);
    m3.at<float>(1, 1) = 30;
    m4.at<float>(1, 1) = 5;
    m3.at<float>(0, 2) = 24;
    m4.at<float>(0, 2) = 6;
    std::cout << "m3:" << std::endl << m3 << std::endl;
    std::cout << "m4:" << std::endl << m4 << std::endl;

    cv::Scalar s1(10, 11, 12);
    cv::Scalar s2(100, 110, 120);

    //MatExpr operator + (const Mat & a, const Mat & b);
    cv::Mat dst1 = m1 + m2;
    std::cout << "dst1:" << std::endl << dst1 << std::endl;

    //MatExpr operator + (const Mat & a, const Scalar & s);
    cv::Mat dst2 = m1 + s1;
    std::cout << "dst2:" << std::endl << dst2 << std::endl;

    //MatExpr operator + (const Scalar & s, const Mat & a);
    cv::Mat dst3 = s1 + m1;
    std::cout << "dst3:" << std::endl << dst3 << std::endl;

    //MatExpr operator - (const Mat & a, const Mat & b);
    cv::Mat dst4 = m1 - m2;
    std::cout << "dst4:" << std::endl << dst4 << std::endl;

    //MatExpr operator - (const Mat & a, const Scalar & s);
    cv::Mat dst5 = m1 - s1;
    std::cout << "dst5:" << std::endl << dst5 << std::endl;

    //MatExpr operator - (const Scalar & s, const Mat & a);
    cv::Mat dst6 = s2 - m1;
    std::cout << "dst6:" << std::endl << dst6 << std::endl;

    //MatExpr operator * (const Mat & a, const Mat & b); 
    cv::Mat dst7 = m3 * m4;
    std::cout << "dst7:" << std::endl << dst7 << std::endl;

    //MatExpr operator * (const Mat & a, double s);
    cv::Mat dst8 = m1 * 2;
    std::cout << "dst8:" << std::endl << dst8 << std::endl;

    //MatExpr operator * (double s, const Mat & a);
    cv::Mat dst9 = 2 * m1;
    std::cout << "dst9:" << std::endl << dst9 << std::endl;

    //MatExpr operator / (const Mat & a, const Mat & b);
    cv::Mat dst10 = m3 / m4;
    std::cout << "dst10:" << std::endl << dst10 << std::endl;

    //MatExpr operator / (const Mat & a, double s);
    cv::Mat dst11 = m1 / 10;
    std::cout << "dst11:" << std::endl << dst11 << std::endl;

    //MatExpr operator / (double s, const Mat & a);
    cv::Mat dst12 = 240 / m1;
    std::cout << "dst12:" << std::endl << dst12 << std::endl;

    //void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype = -1);
    cv::Mat dst13;
    cv::add(m1, m2, dst13);
    std::cout << "dst13:" << std::endl << dst13 << std::endl;

    //void subtract(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype = -1);
    cv::Mat dst14;
    cv::subtract(m1, m2, dst14);
    std::cout << "dst14:" << std::endl << dst14 << std::endl;

    //void multiply(InputArray src1, InputArray src2, OutputArray dst, double scale = 1, int dtype = -1);
    cv::Mat dst15;
    cv::multiply(m3, m4, dst15);
    std::cout << "dst15:" << std::endl << dst15 << std::endl;

    //void divide(InputArray src1, InputArray src2, OutputArray dst, double scale = 1, int dtype = -1);
    cv::Mat dst16;
    cv::divide(m1, m2, dst16);
    std::cout << "dst16:" << std::endl << dst16 << std::endl;

    //saturate_cast
    int dst17 = cv::saturate_cast<uchar>(310);
    std::cout << "dst17:" << std::endl << dst17 << std::endl;

    system("pause");
    return 0;
}

输出结果:
m1:
[ 20,  40,  30,  20,  40,  30,  20,  40,  30;
  20,  40,  30,  20,  40,  30,  20,  40,  30;
  20,  40,  30,  20,  40,  30,  20,  40,  30]
m2:
[ 10,  20,  15,  10,  20,  15,  10,  20,  15;
  10,  20,  15,  10,  20,  15,  10,  20,  15;
  10,  20,  15,  10,  20,  15,  10,  20,  15]
m3:
[1, 1, 24;
 1, 30, 1;
 1, 1, 1]
m4:
[1, 1, 6;
 1, 5, 1;
 1, 1, 1]
dst1:
[ 30,  60,  45,  30,  60,  45,  30,  60,  45;
  30,  60,  45,  30,  60,  45,  30,  60,  45;
  30,  60,  45,  30,  60,  45,  30,  60,  45]
dst2:
[ 30,  51,  42,  30,  51,  42,  30,  51,  42;
  30,  51,  42,  30,  51,  42,  30,  51,  42;
  30,  51,  42,  30,  51,  42,  30,  51,  42]
dst3:
[ 30,  51,  42,  30,  51,  42,  30,  51,  42;
  30,  51,  42,  30,  51,  42,  30,  51,  42;
  30,  51,  42,  30,  51,  42,  30,  51,  42]
dst4:
[ 10,  20,  15,  10,  20,  15,  10,  20,  15;
  10,  20,  15,  10,  20,  15,  10,  20,  15;
  10,  20,  15,  10,  20,  15,  10,  20,  15]
dst5:
[ 10,  29,  18,  10,  29,  18,  10,  29,  18;
  10,  29,  18,  10,  29,  18,  10,  29,  18;
  10,  29,  18,  10,  29,  18,  10,  29,  18]
dst6:
[ 80,  70,  90,  80,  70,  90,  80,  70,  90;
  80,  70,  90,  80,  70,  90,  80,  70,  90;
  80,  70,  90,  80,  70,  90,  80,  70,  90]
dst7:
[26, 30, 31;
 32, 152, 37;
 3, 7, 8]
dst8:
[ 40,  80,  60,  40,  80,  60,  40,  80,  60;
  40,  80,  60,  40,  80,  60,  40,  80,  60;
  40,  80,  60,  40,  80,  60,  40,  80,  60]
dst9:
[ 40,  80,  60,  40,  80,  60,  40,  80,  60;
  40,  80,  60,  40,  80,  60,  40,  80,  60;
  40,  80,  60,  40,  80,  60,  40,  80,  60]
dst10:
[1, 1, 4;
 1, 6, 1;
 1, 1, 1]
dst11:
[  2,   4,   3,   2,   4,   3,   2,   4,   3;
   2,   4,   3,   2,   4,   3,   2,   4,   3;
   2,   4,   3,   2,   4,   3,   2,   4,   3]
dst12:
[ 12,   6,   8,  12,   6,   8,  12,   6,   8;
  12,   6,   8,  12,   6,   8,  12,   6,   8;
  12,   6,   8,  12,   6,   8,  12,   6,   8]
dst13:
[ 30,  60,  45,  30,  60,  45,  30,  60,  45;
  30,  60,  45,  30,  60,  45,  30,  60,  45;
  30,  60,  45,  30,  60,  45,  30,  60,  45]
dst14:
[ 10,  20,  15,  10,  20,  15,  10,  20,  15;
  10,  20,  15,  10,  20,  15,  10,  20,  15;
  10,  20,  15,  10,  20,  15,  10,  20,  15]
dst15:
[1, 1, 144;
 1, 150, 1;
 1, 1, 1]
dst16:
[  2,   2,   2,   2,   2,   2,   2,   2,   2;
   2,   2,   2,   2,   2,   2,   2,   2,   2;
   2,   2,   2,   2,   2,   2,   2,   2,   2]
dst17:
255
相关推荐
2601_968900776 小时前
Agent沙盒基础设施拆解:三层镜像与按需加载的工程取舍
人工智能
楚楚2516 小时前
2026实测:智能体办公平台三周上手真实体验
人工智能
智圣新创016 小时前
教育数据要素流通刚需下 智圣新创高校数据中台解决方案的全域建设落地框架
大数据·人工智能·物联网
xianghongtao01166 小时前
如何选择一台适合你的本地 AI 硬件设备?Lucy AI Studio——从本地 AI 办公到家庭影音的完整指南
人工智能·端脑科技·本地ai硬件设备·kickstarter众筹项目·lucy ai studio·lucy aios
ZhangJun956 小时前
Mobike 共享单车分析项目
人工智能·python·算法·kmeans·聚类·knn
互联网资讯7 小时前
本地创业者入局 AI 短剧,本地化部署怎么选更省钱
大数据·人工智能
唐维康7 小时前
昆工计算机408考研2027招285人,比去年少6人
人工智能·考研·昆明理工大学
Martina_03217 小时前
AI生成的过山车轨道导入后频繁脱轨?用5步检查样条、轨距与碰撞
图像处理·人工智能·游戏·3d·材质·游戏策划·关卡设计
小猴子爱上树7 小时前
跨马翻译:批量图片翻译+视频字幕+智能抠图,跨境电商在线图片翻译工具
大数据·人工智能·python·音视频
佳瑞Jarrett7 小时前
从 0 到 1 手搓 AI 调解训练系统:双 NPC 实时语音 + AI 自动评分(FastAPI + Qwen-Audio Realtime 实战)
人工智能