c++图像像素计算

发布时间:2023年12月20日

? ? ? ?我们知道每张图像都能够用矩阵来表示,矩阵中每个元素的值表示了图像中每个像素值,像素值的大小就对应着图像的亮暗。因此找到矩阵中的最大值,就是找到了图像中灰度值最大的像素,计算矩阵所有元素的平均值就是计算图像像素平均灰度,平均灰度表示图像整体的亮暗程度。

图像像素计算有以下几种:

1、寻找图像中最大像素值和最小像素值

可以利用opencv的minMaxLoc()函数实现

void cv::minMaxLoc(InputArray src,
                   double * minVal,
                   double * maxVal = 0,
                   Point * minLoc = 0,
                   Point * maxLoc = 0,
                   InputArray mask = noArray())
  • src:需要寻找最大值和最小值的图像或者矩阵,要求必须是单通道矩阵
  • minVal:图像或者矩阵中的最小值。
  • maxVal:图像或者矩阵中的最大值。
  • minLoc:图像或者矩阵中的最小值在矩阵中的坐标。
  • maxLoc:图像或者矩阵中的最大值在矩阵中的坐标。
  • mask:掩模,用于设置在图像或矩阵中的指定区域寻找最值。

Point数据类型是用于表示图像的像素坐标,由于图像的像素坐标轴以左上角为坐标原点,水平方向为x轴,垂直方向为y轴,因此Point(x,y)对应于图像的行和列表示为Point(列数,行数)。在OpenCV中对于2D坐标和3D坐标都设置了多种数据类型,针对2D坐标数据类型定义了整型坐标cv::Point2i(或者cv::Point)、double型坐标cv::Point2d、浮点型坐标cv::Point2f,对于3D坐标同样定义了上述的坐标数据类型,只需要将其中的数字“2”变成“3”即可。对于坐标中x、y、z轴的具体数据,可以通过变量的x、y、z属性进行访问,例如Point.x可以读取坐标的x轴数据。
对于多通道矩阵数据,利用cv::Mat::reshape()将多通道变成单通道,或者分别寻找每个通道的最值,然后再进行比较寻找到全局最值。

具体使用案例如下:

#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"

using namespace std;
using namespace cv;

int main(int argc,char** argv) {
    cout<<"OpenCv Version: "<<CV_VERSION<<endl;//输出使用的opencv版本号
    Mat img=imread('1.jpg');//单通道图像
    Mat imgs=imread("2.jpg");//多通道图像
    double minVal,maxVal;//用于存放矩阵中的最大值和最小值
    Point minIdx,maxIdx;//用于存放矩阵中的最大值和最小值的位置

    /*寻找单通道矩阵中的最值*/
    minMaxLoc(img,&maxVal,&minVal,&minIdx,&maxIdx);
    cout << "img中最大值是:" << maxVal << " " << "在矩阵中的位置:" << maxIdx << endl;
    cout << "img中最小值是:" << minVal << " " << "在矩阵中的位置:" << minIdx << endl;

    /*寻找多通道矩阵中的最值*/
    Mat imgs_re=imgs.reshape(1,4);//将多通道矩阵变成单通道矩阵
    minMaxLoc(imgs_re,&minVal,&maxVal,&minIdx,&maxIdx);
    cout << "img中最大值是:" << maxVal << " " << "在矩阵中的位置:" << maxIdx << endl;
    cout << "img中最小值是:" << minVal << " " << "在矩阵中的位置:" << minIdx << endl;
    return 0;
}
2、计算图像的均值和标准差

如果我们想知道图像的亮暗程度变化,可以求图像的均值来判断。均值越大,说明图像越亮。图像标准差表示图像中明暗变化程度,标准差越大表示图像中明暗变化越明显。

我们可以利用cv::mean()函数用于计算图像的平均值,也可以利用meanStdDev()函数用于同时计算图像的均值和标准方差。

cv::Scalar cv::mean(InputArray src,InputArray mask = noArray())
  • src:待求平均值的图像矩阵。
  • mask:掩模,用于标记求取哪些区域的平均值。


该函数用来求取图像矩阵的每个通道的平均值,函数的第一个参数用来输入待求平均值的图像矩阵,其通道数目可以在1到4之间。需要注意的是,该函数的返回值是一个cv::Scalar类型的变量,函数的返回值有4位,分别表示输入图像4个通道的平均值,如果输入图像只有1个通道,那么返回值的后三位都为0,例如输入该函数一个单通道平均值为1的图像,输出的结果为[1,0,0,0],可以通过cv::Scalar[n]查看第n个通道的平均值。该函数的第二个参数用于控制图像求取均值的范围,在第一个参数中去除第二个参数中像素值为0的像素,当不输入第二个参数时,表示求取第一个参数全部像素的平均值。

void cv::meanStdDev(InputArray src,OutputArray mean,OutputArray stddev,InputArray mask = noArray())
  • src:待求平均值的图像矩阵。
  • mean:图像每个通道的平均值,参数为Mat类型变量。
  • stddev:图像每个通道的标准方差,参数为Mat类型变量。
  • mask:掩模,用于标记求取哪些区域的平均值和标准方差。

该函数的第一个参数与前面mean()函数第一个参数相同,都可以是1-4通道的图像,不同之处在于该函数没有返回值,图像的均值和标准方差输出在函数的第二个和第三个参数中,区别于mean()函数,用于存放平均值和标准方差的是Mat类型变量,变量中的数据个数与第一个参数通道数相同,如果输入图像只有一个通道,该函数求取的平均值和标准方差变量中只有一个数据。
具体使用案例如下:

#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"

using namespace std;
using namespace cv;

int main(int argc,char** argv) {
    cout<<"OpenCv Version: "<<CV_VERSION<<endl;
    Mat img=imread("3.jpg");//单通道图像或矩阵
    Mat imgs=imread("4.jpg");//多通道图像或矩阵

    cout << "/* 用meanStdDev同时求取图像的均值和标准方差 */" << endl;
    Scalar myMean;
    myMean=mean(imgs);
    cout<<"imgs均值 = "<<myMean<<endl;
    cout<<"imgs第一个通道的均值 = "<<myMean[0]<<" "
        <<"imgs第二个通道的均值 = "<<myMean[1]<<endl;

    cout << "/* 用meanStdDev同时求取图像的均值和标准方差 */" << endl;
    Mat myMeanMat,myStddevMat;

    meanStdDev(img,myMeanMat,myStddevMat);
    cout << "img均值=" << myMeanMat << " " << endl;
    cout << "img标准方差=" << myStddevMat << endl << endl;
    meanStdDev(imgs,myMeanMat,myStddevMat);
    cout << "img均值=" << myMeanMat << " " << endl;
    cout << "img标准方差=" << myStddevMat << endl << endl;
    return 0;
}
3、两张图像比较运算

opencv提供了求取两张图像每一位像素较大或者较小灰度值的max()、min()函数,这两个函数分别比较两个图像中每一位元素灰度值的大小,保留较大(较小)的灰度值。

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

该函数的功能相对来说比较简单,就是比较图像每个像素的大小,按要求保留较大值或者较小值,最后生成新的图像。

具体案例如下:

#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"

using namespace std;
using namespace cv;

int main(int argc,char** argv) {
    cout<<"OpenCv Version: "<<CV_VERSION<<endl;
    //对两张彩色图像进行比较运算
    Mat img1=imread("l.png");
    Mat img2=imread("2.jpg");
    if(img0.empty()||img1.empty()){
        cout<<"请确认图像文件名称是否正确"<<endl;
        return -1;
    }
    Mat comMin,comMax;
    max(img1,img2,comMax);
    min(img1,img2,comMin);
    imshow("comMin",comMin);
    imshow("comMax",comMax);

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

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

    //对两张图片灰度图像进行比较运算
    Mat img1g,img2g,comMing,comMaxg;
    cvtColor(img1,img1g,COLOR_BGR2GRAY);
    cvtColor(img2,img2g,COLOR_BGR2GRAY);
    max(img1g,img2g,comMaxg);
    max(img1g,img2g,comMaxg);
    imshow("comMing",comMing);
    imshow("comMaxg",comMaxg);
    return 0;
}
4、图片逻辑运算

opencv为两个图像像素之间逻辑运算与、或、异或以及非运算提供了bitwise_and()、bitwise_or()、bitwise_xor()和bitwise_not()四个函数,在进行逻辑计算时,一定要保证两个图像矩阵之间的尺寸、数据类型和通道数相同,多个通道进行逻辑运算时不同通道之间是独立进行的。

具体案例如下:

#include <opencv2\opencv.hpp>
#include <iostream>
#include <vector>
 
using namespace std;
using namespace cv;

int main()
{
   Mat img = imread("lena.png");
   if (img.empty())
  {
     cout << "请确认图像文件名称是否正确" << endl;
      return -1;
   }
   //创建两个黑白图像
  Mat img0 = Mat::zeros(200, 200, CV_8UC1);
  Mat img1 = Mat::zeros(200, 200, CV_8UC1);
  Rect rect0(50, 50, 100, 100);
  img0(rect0) = Scalar(255);//将起点50,50,长宽100的矩形框区域像素值置为255,白色
  Rect rect1(100, 100, 100, 100);
  img1(rect1) = Scalar(255);
  imshow("img0", img0);
  imshow("img1", img1);
  //进行逻辑运算
  Mat myAnd, myOr, myXor, myNot, imgNot;
  bitwise_not(img0, myNot);
  bitwise_and(img0, img1, myAnd);
  bitwise_or(img0, img1, myOr);
  bitwise_xor(img0, img1, myXor);
  bitwise_not(img, imgNot);
  imshow("myAnd", myAnd);
  imshow("myOr", myOr);
  imshow("myXor", myXor);
  imshow("myNot", myNot);
  imshow("img", img);
  imshow("imgNot", imgNot);
  waitKey(0);
  return 0;
  }

文章来源:https://blog.csdn.net/wangmengmeng99/article/details/135107164
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。