【从零学习OpenCV 4】两图像间的像素操作

重磅干货,第一时间送达

经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《从零学习OpenCV 4》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

前面介绍的计算最值、平均值等操作都是对一张图像进行处理,接下来将介绍两张图像间像素的相关操作,包含两张图像的比较运算、逻辑运算等。

1

01

两张图像的比较运算

OpenCV 4中提供了求取两张图像每一位像素较大或者较小灰度值的max()、min()函数,这两个函数分别比较两个图像中每一位元素灰度值的大小,保留较大(较小)的灰度值,这两个函数的函数原型在代码清单3-13中给出。

代码清单3-13 max()和min()函数原型
1.  void cv::max(InputArray src1,
2.               InputArray src2,
3.               OutputArray dst
4.                  )
5.  void cv::min(InputArray src1,
6.               InputArray src2,
7.               OutputArray dst
8.                  )
  • src1:第一个图像矩阵,可以是任意通道数的矩阵。

  • src2:第二个图像矩阵,尺寸和通道数以及数据类型都需要与src1一致。

  • dst:保留对应位置较大(较小)灰度值后的图像矩阵,尺寸、通道数和数据类型与src1一致。

该函数的功能相对来说比较简单,就是比较图像每个像素的大小,按要求保留较大值或者较小值,最后生成新的图像。例如,第一张图像位置像素值为100,第二张图像位置像素值为10,那么输出图像位置像素值为100。在代码清单3-14中给出了这两个函数的代码实现过程以及运算结果,运算结果在图3-9、图3-10和图3-11中给出。这种比较运算主要用在对矩阵类型数据的处理,与掩模图像进行比较运算可以实现抠图或者选择通道的效果。

代码清单3-14 myMaxAndMin.cpp两个矩阵或图像进行比较运算
1.  #include <opencv2\opencv.hpp>
2.  #include <iostream>
3.  #include <vector>
4.  
5.  using namespace std;
6.  using namespace cv;
7.  
8.  int main()
9. {
10.    float a[12] = { 1, 2, 3.3, 4, 5, 9, 5, 7, 8.2, 9, 10, 2 };
11.    float b[12] = { 1, 2.2, 3, 1, 3, 10, 6, 7, 8, 9.3, 10, 1 };
12.    Mat imga = Mat(3, 4, CV_32FC1, a);
13.    Mat imgb = Mat(3, 4, CV_32FC1, b);
14.    Mat imgas = Mat(2, 3, CV_32FC2, a);
15.    Mat imgbs = Mat(2, 3, CV_32FC2, b);
16.  
17.    //对两个单通道矩阵进行比较运算
18.    Mat myMax, myMin;
19.    max(imga, imgb, myMax);
20.    min(imga, imgb, myMin);
21.  
22.    //对两个多通道矩阵进行比较运算
23.    Mat myMaxs, myMins;
24.    max(imgas, imgbs, myMaxs);
25.    min(imgas, imgbs, myMins);
26.  
27.    //对两张彩色图像进行比较运算
28.    Mat img0 = imread("lena.png");
29.    Mat img1 = imread("noobcv.jpg");
30.    if (img0.empty()|| img1.empty())
31.    {
32.      cout << "请确认图像文件名称是否正确" << endl;
33.      return -1;
34.    }
35.    Mat comMin, comMax;
36.    max(img0, img1, comMax);
37.    min(img0, img1, comMin);
38.    imshow("comMin", comMin);
39.    imshow("comMax", comMax);
40.  
41.    //与掩模进行比较运算
42.    Mat src1 = Mat::zeros(Size(512, 512), CV_8UC3);
43.    Rect rect(100, 100, 300, 300);
44.    src1(rect) = Scalar(255, 255, 255); //生成一个低通300*300的掩模
45.    Mat comsrc1, comsrc2;
46.    min(img0, src1, comsrc1);
47.    imshow("comsrc1", comsrc1);
48.  
49.    Mat src2 = Mat(512, 512, CV_8UC3, Scalar(0,0, 255)); //生成一个显示红色通道的低通掩模
50.    min(img0, src2, comsrc2);
51.    imshow("comsrc2", comsrc2);
52.  
53.    //对两张灰度图像进行比较运算
54.    Mat img0G, img1G, comMinG, comMaxG;
55.    cvtColor(img0, img0G, COLOR_BGR2GRAY);
56.    cvtColor(img1, img1G, COLOR_BGR2GRAY);
57.    max(img0G, img1G, comMaxG);
58.    min(img0G, img1G, comMinG);
59.    imshow("comMinG", comMinG);
60.    imshow("comMaxG", comMaxG);
61.    waitKey(0);
62.    return 0;
63.  }

图3-9 maxAndMin.cpp程序中两个矩阵进行比较运算结果

图3-10 axAndMin.cpp程序中两个彩色图像和灰度图像进行比较运算结果

图3-11 与掩模图像进行比较运算结果

1

02

两张图像的逻辑运算

OpenCV 4针对两个图像像素之间的与、或、异或以及非运算提供了bitwise_and()、bitwise_or()、bitwise_xor()和bitwise_not()四个函数,在代码清单3-15中给出了这四个函数的函数原型。在了解函数用法之前,我们先了解一下图像像素逻辑运算的规则。图像像素间的逻辑运算与数字间的逻辑运算相同,具体规则在图3-12中给出。像素的非运算只能针对一个数值进行,因此在图3-12中对像素求非运算时对图像1的像素值进行非运算。如果像素取值只有0和1的话,那么图中的前4行数据正好对应了所有的运算规则,但是CV_8U类型的图像像素值从0取到255,此时的逻辑运算就需要将像素值转成二进制数后再进行,因为CV_8U类型是8位数据,因此对0求非是11111111,也就是255。在图3-12中最后一行数据中,像素值5对应的二进制为101,像素值6对应的二进制是110,因此与运算得100(4),或运算得111(7),异或运算得011(3),对像素值5进行非运算得11111010(250)。了解了像素的辑运算原理之后,我们再来看OpenCV 4中提供的辑运算函数的使用方法。

图3-12 图像逻辑运算规则

代码清单3-15 OpenCV 4中像素逻辑运算函数原型
1.  //像素求与运算
2.  void cv::bitwise_and(InputArray src1,
3.                           InputArray src2,
4.                           OutputArray dst,
5.                           InputArray mask = noArray()
6.                           )
7.  //像素求或运算
8.  void cv::bitwise_or(InputArray src1,
9.                     InputArray src2,
10.                     OutputArray dst,
11.                     InputArray mask = noArray()
12.                       )
13.  //像素求异或运算
14.  void cv::bitwise_xor(InputArray src1,
15.                      InputArray src2,
16.                      OutputArray dst,
17.                      InputArray mask = noArray()
18.                        )
19.  //像素求非运算
20.  void cv::bitwise_not(InputArray src,
21.                      OutputArray dst,
22.                      InputArray mask = noArray()
23.                        )
  • src1:第一个图像矩阵,可以是多通道图像数据。

  • src2:第二个图像矩阵,尺寸和通道数以及数据类型都需要与src1一致。

  • dst:逻辑运算输出结果,尺寸和通道数和数据类型与src1一致。

  • mask:掩模,用于设置图像或矩阵中逻辑运算的范围。

这几个函数都执行相应的逻辑运算,在进行逻辑计算时,一定要保证两个图像矩阵之间的尺寸、数据类型和通道数相同,多个通道进行逻辑运算时不同通道之间是独立进行的。为了更加直观的理解两个图像像素间的逻辑运算,在代码清单3-16中给出两个黑白图像像素逻辑运算的示例程序,最后运行结果在图3-13中给出。

代码清单3-16 myLogicOperation.cpp两个图像像素逻辑运算
1.  #include <opencv2\opencv.hpp>
2.  #include <iostream>
3.  #include <vector>
4.  
5.  using namespace std;
6.  using namespace cv;
7.  
8.  int main()
9. {
10.    Mat img = imread("lena.png");
11.    if (img.empty())
12.    {
13.      cout << "请确认图像文件名称是否正确" << endl;
14.      return -1;
15.    }
16.    //创建两个黑白图像
17.    Mat img0 = Mat::zeros(200, 200, CV_8UC1);
18.    Mat img1 = Mat::zeros(200, 200, CV_8UC1);
19.    Rect rect0(50, 50, 100, 100);
20.    img0(rect0) = Scalar(255);
21.    Rect rect1(100, 100, 100, 100);
22.    img1(rect1) = Scalar(255);
23.    imshow("img0", img0);
24.    imshow("img1", img1);
25.  
26.    //进行逻辑运算
27.    Mat myAnd, myOr, myXor, myNot, imgNot;
28.    bitwise_not(img0, myNot);
29.    bitwise_and(img0, img1, myAnd);
30.    bitwise_or(img0, img1, myOr);
31.    bitwise_xor(img0, img1, myXor);
32.    bitwise_not(img, imgNot);
33.    imshow("myAnd", myAnd);
34.    imshow("myOr", myOr);
35.    imshow("myXor", myXor);
36.    imshow("myNot", myNot);
37.    imshow("img", img);
38.    imshow("imgNot", imgNot);
39.    waitKey(0);
40.    return 0;
41.  }

图3-13 logicOperation.cpp程序运行结果

(0)

相关推荐

  • OpenCV探索之路(四):膨胀、腐蚀、开闭运算

    腐蚀和膨胀是最基本的形态学运算. 腐蚀和膨胀是针对白色部分(高亮部分)而言的. 膨胀就是对图像高亮部分进行"领域扩张",效果图拥有比原图更大的高亮区域:腐蚀是原图中的高亮区域被蚕食 ...

  • OpenCV探索之路(五):图片缩放和图像金字塔

    对图像进行缩放的最简单方法当然是调用resize函数啦! resize函数可以将源图像精确地转化为指定尺寸的目标图像. 要缩小图像,一般推荐使用CV_INETR_AREA来插值:若要放大图像,推荐使用 ...

  • 自适应阈值化操作:adaptiveThreshold()函数

    在图像阈值化操作中,更关注的是从二值化图像中,分离目标区域和背景区域,但是仅仅通过设定固定阈值很难达到理想的分割效果.而自适应阈值,则是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值.这样 ...

  • OpenCV探索之路(十三):详解掩膜mask

    在OpenCV中我们经常会遇到一个名字:Mask(掩膜).很多函数都使用到它,那么这个Mask到底什么呢? 一开始我接触到Mask这个东西时,我还真是一头雾水啊,也对无法理解Mask到底有什么用.经过 ...

  • 【从零学习OpenCV 4】图像修复

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像矩的计算与应用

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像膨胀

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像距离变换

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像中添加高斯噪声

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像中添加椒盐噪声

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像模板匹配

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像直方图绘制

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像金字塔

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...