opencv(8)---访问图像像素

来源:互联网 发布:php是最好的语言 编辑:程序博客网 时间:2024/05/21 17:01

预备知识

1. 图像在内存中的存储形式

图像矩阵的大小取决于所采用的通道数
1)灰度矩阵的存储方式

这里写图片描述

2)彩色图像的存储方式
这里写图片描述

注意:
opencv的通道顺序是BGR,而不是RGB

下面进行验证
代码1 :

 Mat mat(200,300,CV_8UC3,Scalar(255,0,0)); imshow("Blue---Scalar(255,0,0)",mat);

运行结果:
这里写图片描述

代码2:

  Mat mat(200,300,CV_8UC3,Scalar(0,255,0));  imshow("Green---Scalar(0,255,0)",mat);

运行结果
这里写图片描述

2.判断矩阵存储是否连续

isContinuous()

访问图像中像素方法

1 动态地址访问

1 代码

这里写图片描述

#include "mainwindow.h"#include <QApplication>#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;int main(int argc, char *argv[]){    QApplication a(argc, argv);    //    MainWindow w;    //    w.show();    Mat img=imread("D:\\1\\1.png");    if(img.empty()){        cout<<"no Picture readed"<<endl;        return 0;    }    Mat dst=img.clone();    int rowNumber=img.rows;//获取行数    int colNumber=img.cols;//获取列数    cout<<rowNumber<<endl;    cout<<colNumber<<endl;    for(int i=0;i<rowNumber;i++){        for(int j=0;j<colNumber;j++){            dst.at<Vec3b>(i,j)[0]=255;//蓝色通道            dst.at<Vec3b>(i,j)[1]=0;//绿色通道            dst.at<Vec3b>(i,j)[2]=0;//红色通道        }    }    imshow("img",img);    imshow("dst",dst);    waitKey(0);    destroyAllWindows();    return a.exec();}

2 运行结果

这里写图片描述
这里写图片描述

3 知识点详解
成员函数at用来读取像素
1) 对于彩色三通道图像
对图像像素的赋值方式为:

image.at<Vec3b>(i,j)[channel] = value;

at方法不会进行类型转换,所以需要制定图像元素类型,并且要和矩阵内类型一致

使用Vec3b进行类型转换
其中,

channel

取值为0,1,2 0—-蓝色通道 1—绿色通道 2—红色通道

2) 对于灰度图像

dst.at<uchar>(i,j)=255;//灰度图像

使用uchar进行类型转换

2 指针访问

1)代码
这里写图片描述

  /*指针访问*/    Mat img=imread("D:\\1\\1.png");    if(img.empty()){        cout<<"no Picture readed"<<endl;        return 0;    }    Mat dst=img.clone();    int rowNumber=img.rows;//获取行数    int colNumber=img.cols*img.channels();//每一行的元素个数=列数*通道数    cout<<rowNumber<<endl;    cout<<colNumber<<endl;    for(int i=0;i<rowNumber;i++){        uchar *data=dst.ptr<uchar>(i);//获取第i行首地址        for(int j=0;j<colNumber;j++){//列循环            switch(j%3){//RGB图像通道区分            case 0:                data[j]=255;                break;            case 1:                data[j]=0;                break;            case 2:                data[j]=0;                break;            default:                break;            }        }    }    imshow("img",img);    imshow("dst",dst);    waitKey(0);    destroyAllWindows();    return a.exec();

速度
最快
2)运行结果
这里写图片描述
这里写图片描述
3)知识点详解

 uchar *data=dst.ptr<uchar>(i);

Mat类提供了ptr函数可以得到图像任意行的首地址。
使用uchar进行强制地址转换。

3 迭代器

这里写图片描述
速度
介于上面两种方式之间

简单应用

减色效果

1. 代码

#include "mainwindow.h"#include <QApplication>#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;int main(int argc, char *argv[]){    QApplication a(argc, argv);    /*指针访问*/    Mat img=imread("D:\\1\\1.png");    if(img.empty()){        cout<<"no Picture readed"<<endl;        return 0;    }    Mat dst=img.clone();    int rowNumber=img.rows;//获取行数    int colNumber=img.cols*img.channels();//每一行的元素个数=列数*通道数    cout<<rowNumber<<endl;    cout<<colNumber<<endl;    for(int i=0;i<rowNumber;i++){        uchar *data=dst.ptr<uchar>(i);//获取第i行首地址        for(int j=0;j<colNumber;j++){//列循环            switch(j%3){//RGB图像通道区分            case 0:                data[j]=data[j]/64*64+64/2;                break;            case 1:                data[j]=data[j]/64*64+64/2;                break;            case 2:                data[j]=data[j]/64*54+64/2;                break;            default:                break;            }        }    }    imshow("img",img);    imshow("dst",dst);    waitKey(0);    destroyAllWindows();    return a.exec();}

2. 运行结果
这里写图片描述
这里写图片描述

雪花效果

1.代码

#include "mainwindow.h"#include <QApplication>#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;int main(int argc, char *argv[]){    QApplication a(argc, argv);    /*指针访问*/    Mat img=imread("D:\\1\\1.png");    if(img.empty()){        cout<<"no Picture readed"<<endl;        return 0;    }    Mat dst=img.clone();    int rowNumber=img.rows;//获取行数    int colNumber=img.cols;//每一行的元素个数=列数*通道数    int i,j;    for(int k=0;k<200;k++){        i=rand()%rowNumber;        j=rand()%colNumber;        dst.at<Vec3b>(i,j)[0]=255;        dst.at<Vec3b>(i,j)[1]=255;        dst.at<Vec3b>(i,j)[2]=255;    }    imshow("img",img);    imshow("dst",dst);    waitKey(0);    destroyAllWindows();    return a.exec();}

2 运行结果

这里写图片描述
这里写图片描述

0 0
原创粉丝点击