opencv 图像读取显示和像素操作



从今天起,开始从头系统学习下opencv,下面记录下图像的基本操作:

1. 图像的读取和显示

Mat image = imread(imagePath, 1);
第二个参数表示图片读入的方式(flags可以缺省,缺省时flags=1,表示以彩色图片方式读入图片)
flags>0时表示以彩色方式读入图片
flags=0时表示以灰度图方式读入图片
flags<0时表示以图片的本来的格式读入图片。

char *f = "E:\\opencv\\sources\\samples\\wp8\\OpenCVXaml\\OpenCVXaml\\Assets\\Lena.png";
    Mat lena;
    lena = imread(f);
    imshow("lena", lena);
  
  
  • 1
  • 2
  • 3
  • 4
    IplImage * lena2;
    //lena2 = cvLoadImage(f, CV_LOAD_IMAGE_GRAYSCALE); // 加载灰度图
    lena2 = cvLoadImage(f, CV_LOAD_IMAGE_UNCHANGED);//加载原始图像
    cvNamedWindow("lena2", CV_WINDOW_AUTOSIZE);//创建窗口
    cvShowImage("lena2", lena2);
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
    -

像素读取和操作

1. 利用cv::Mat的at函数,直接访问具体地址

void get_setImagePixel(char *imagePath , int x , int y)
{
//  Mat image = imread(imagePath , 0);
    Mat image = imread(imagePath, 1);
    //得宽高
    int w = image.cols;
    int h = image.rows;

    int channels = image.channels();
    if (x < w && y < h)
    {
        //灰度图,像素为单通道
        if (channels == 1)
        {
            int pixel = image.at<uchar>(x, y);
            cout << "灰度图像,处的灰度值为" << pixel << endl;
        }
        else
        {
            //通过实验,彩色图像的默认存储是bgr, 且存储的格式如下

            //读取
            int b = image.at<Vec3b>(x, y)[0]; // b = image.at<uchar>(x,y*3);
            cout << b << endl;
            int g = image.at<Vec3b>(x, y)[1]; //g = image.at<uchar>(x, y * 3 + 1);
            cout << g << endl;
            int r = image.at<Vec3b>(x, y)[2]; //r = image.at<uchar>(x, y * 3 + 1);
            cout << r << endl;

            //设置像素值
            image.at<Vec3b>(x, y)[0] = 255;
            image.at<Vec3b>(x, y)[1] = 255;
            image.at<Vec3b>(x, y)[2] = 255;
         }
    }
    imshow("cc", image);
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

2. 利用Mat 的prt 函数:行首地址访问

void get_setImagePixel2(char *imagePath, int x, int y)
{
    Mat image = imread(imagePath, 1);
    //得宽高
    int w = image.cols;
    int h = image.rows;
    int channels = image.channels();
    //如果图像连续 ,可以将数据转化为1维数组,提高访问效率,但对少量像素访问就没必要
    //if (image.isContinuous())
    //{
    //  //reshape函数用于改变矩阵维度  
    //  //图像行数为1,列数为原先的行数乘上列数  
    //  image.reshape(1, image.cols*image.rows);
    //}

    //获得第y行的首地址
    uchar *data = image.ptr<uchar>(y);
    int position = x*channels;
    if (channels == 1)
    {
        int pixel = data[position];
        cout << "灰度图像,处的灰度值为" << pixel << endl;
    }
    else
    {
        //通过实验,彩色图像的默认存储是bgr, 且存储的格式如下

        //读取
        int b = data[position];
        cout << b << endl;
        int g = data[position+1];
        cout << g << endl;
        int r = data[position+2];
        cout << r << endl;

        //设置像素值
        data[position] = 255;
        data[position+1] = 255;
        data[position+2] = 255;
    }
    imshow("cc", image);
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

3. 利用迭代器遍历图像

void get_setImagePixel3(char *imagePath, int x, int y)
{
    Mat image = imread(imagePath, 1);
    //得宽高
    int w = image.cols;
    int h = image.rows;
    int channels = image.channels();


    if (channels == 1)
    {
        //得到初始位置的迭代器  
        Mat_<uchar>::iterator it = image.begin<uchar>();
        //得到终止位置的迭代器  
        Mat_<uchar>::iterator itend = image.end<uchar>();
        int pixel = *(it + y * w + x);
        cout << "灰度图像,处的灰度值为" << pixel << endl;
    }
    else
    {
        //得到初始位置的迭代器  
        Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
        //得到终止位置的迭代器  
        Mat_<Vec3b>::iterator itend = image.end<Vec3b>();
        //读取
        it = it + y * w + x;
        int b = (*it)[0];
        cout << b << endl;
        int g = (*it)[1];
        cout << g << endl;
        int r = (*it)[2];
        cout << r << endl;


        //设置像素值
            (*it)[0] = 255;
            (*it)[1] = 255;
            (*it)[2] = 255;

    }
    imshow("cc", image);

}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

若是大量访问数据和更改数据时用第二种方式效率高。

Node: 在修改像素时候,最好先用变量存储,设定好了再赋值给Mat成员对象,如data,因为如果直接进行操作时,当一个分量值大于255时,向前进1的原则,则会修改前面像素的值,如下:

void colorReduce(cv::Mat&image, int div)
{
    int nl = image.rows; //图像的行数  
    //图像每行的像素数  
    int nc = image.cols * image.channels();
    for (int j = 0; j<nl; j++)
    {
        //得到第j行的首地址  
        uchar* data = image.ptr<uchar>(j);
        //遍历每行的像素  
        for (int i = 0; i<nc; i++)
        {
            //printf("%d    ", data[i]);
            //data[i] = data[i] / div*div + 6;// 这里需要用c来存储,因为如果大于255时会向前进1,则影响前面的像素,data[i] 会自己变得小255
            int c = data[i] / div*div + 100;        
            data[i] =  c > 255 ? 255 : c;    //将每个像素值都变为div的倍数,即将颜色数缩减了div倍                         

        }
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20


从今天起,开始从头系统学习下opencv,下面记录下图像的基本操作:

猜你喜欢

转载自blog.csdn.net/zhangxz259/article/details/81563330