C++版本OpenCv教程(十三)两图像间的像素操作

两张图像的比较运算

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

void cv::max(InputArray src1,InputArray src2,OutputArray dst)
void cv::min(InputArray src1,InputArray src2,OutputArray dst)
  • src1:第一个图像矩阵,可以是任意通道数的矩阵。
  • src2:第二个图像矩阵,尺寸和通道数以及数据类型都需要与src1一致。
  • dst:保留对应位置较大(较小)灰度值后的图像矩阵,尺寸、通道数和数据类型与src1一致。

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

#include
#include
#include
#include 
#include "opencv/highgui.h"

using namespace std;
using namespace cv;

int main(int argc,char** argv) {
    cout<<"OpenCv Version: "<<CV_VERSION<<endl;
    float a[12]={1,2,3.3,4,5,9,5,7,8.2,9,10,2};
    float b[12]={1,2.2,3,1,3,10,6,7,8,9.3,10,1};
    Mat imga=Mat(3,4,CV_32FC1,a);
    Mat imgb=Mat(3,4,CV_32FC1,b);
    Mat imgas=Mat(2,3,CV_32FC2,a);
    Mat imgbs=Mat(2,3,CV_32FC2,b);

    //对两个单通道矩阵进行比较远算
    Mat myMax,myMin;
    max(imga,imgb,myMax);
    min(imga,imgb,myMin);

    //对两个多通道矩阵进行比较运算
    Mat myMaxs,myMins;
    max(imgas,imgbs,myMaxs);
    min(imgas,imgbs,myMins);

    //对两张彩色图像进行比较运算
    Mat img0=imread("lena.png");
    Mat img1=imread("noobcv.jpg");
    if(img0.empty()||img1.empty()){
        cout<<"请确认图像文件名称是否正确"<<endl;
        return -1;
    }
    Mat comMin,comMax;
    max(img0,img1,comMax);
    min(img0,img1,comMin);
    imshow("comMin",comMin);
    imshow("comMax",comMax);

    //与掩模进行比较运算
    Mat src1=Mat::zeros(Size(512,512),CV_8UC3);
    Rect rect(100,100,300,300);
    src1(rect)=Scalar(255,255,255);//生成一个300*300的掩模
    Mat comsrc1,comsrc2;
    min(img0,src1,comsrc1);
    imshow("comsrc1",comsrc1);

    Mat src2=Mat(512,512,CV_8UC3,Scalar(0,0,255));//生成一个显示红色的低通掩模
    min(img0,src2,comsrc2);
    imshow("comsrc2",comsrc2);

    //对两张图片灰度图像进行比较运算
    Mat img0G,img1G,comMinG,comMaxG;
    cvtColor(img0,img0G,COLOR_BGR2GRAY);
    cvtColor(img1,img1G,COLOR_BGR2GRAY);
    max(img0G,img1G,comMaxG);
    max(img0G,img1G,comMaxG);
    imshow("comMinG",comMinG);
    imshow("comMaxG",comMaxG);
    return 0;
}

C++版本OpenCv教程(十三)两图像间的像素操作_第1张图片C++版本OpenCv教程(十三)两图像间的像素操作_第2张图片C++版本OpenCv教程(十三)两图像间的像素操作_第3张图片

两张图像的逻辑运算

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中提供的辑运算函数的使用方法。
C++版本OpenCv教程(十三)两图像间的像素操作_第4张图片

 -  //像素求与运算
 -  void cv::bitwise_and(InputArray src1,
 -                           InputArray src2,
 -                           OutputArray dst,
 -                           InputArray mask = noArray()
 -                           )
 -  //像素求或运算
 -  void cv::bitwise_or(InputArray src1,
 -                     InputArray src2,
 -                     OutputArray dst,
 -                     InputArray mask = noArray()
 -                       )
 -  //像素求异或运算
 -  void cv::bitwise_xor(InputArray src1,
 -                      InputArray src2,
 -                      OutputArray dst,
 -                      InputArray mask = noArray()
 -                        )
 -  //像素求非运算
 -  void cv::bitwise_not(InputArray src,
 -                      OutputArray dst,
 -                      InputArray mask = noArray()
 -                        )
  • src1:第一个图像矩阵,可以是多通道图像数据。
  • src2:第二个图像矩阵,尺寸和通道数以及数据类型都需要与src1一致。
  • dst:逻辑运算输出结果,尺寸和通道数和数据类型与src1一致。
  • mask:掩模,用于设置图像或矩阵中逻辑运算的范围。

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

1.  #include 
2.  #include 
3.  #include 
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.  }

C++版本OpenCv教程(十三)两图像间的像素操作_第5张图片

你可能感兴趣的:(OpenCV)