OpenCV基础篇之像素访问

OpenCV基础篇之像素访问

程序及分析

/*
 * FileName : get_pixels.cpp
 * Author  : xiahouzuoxin @163.com
 * Version  : v1.0
 * Date    : Sun 01 Jun 2014 06:40:54 PM CST
 * Brief    :
 *
 * Copyright (C) MICL,USTB
 */
#include <cv.h>
#include <highgui.h>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    if (argc < 2) {
        cout << "Usage: ./get_pixels [imag name]" << endl;
        return -1;
    }

Mat img;

img = imread(argv[1], 1);


    /*
    * Reverse pixels
    */
    Mat out1 = img.clone();  // change dst will not affect img

long n_rows = out1.rows;
    long n_cols = out1.cols * out1.channels();

/*
    * Row pointer
    */
    uchar *p;
    for (long i=0; i<n_rows; i++) {
        p = out1.ptr<uchar>(i);
        for (long j=0; j<n_cols; j++) {
            p[j] = 255 - p[j];
        }
    }

/*
    * Element pointer
    */
    Mat out2;
    out2.create(img.size(), img.type());  // reserve size and type but alloc new space

n_rows = out2.rows;
    n_cols = out2.cols * out2.channels();

p = out2.data;
    double c = 0.5;
    double b = 30;
    for (long i=0; i<n_rows*n_cols; i++) {
      *(p+i) = (uchar)(255 * 0.5 * ((double)(img.data[i]) / 255) + b);
    }

/*
    * Display
    */
    namedWindow("src_image", CV_WINDOW_NORMAL);
    imshow("src_image", img);
    namedWindow("reverse_image", CV_WINDOW_NORMAL);
    imshow("reverse_image", out1);
    namedWindow("mici_image", CV_WINDOW_NORMAL);
    imshow("mici_image", out2);

waitKey(0);

return 0;
}
 1.
基于元素指针的像素访问:根据Mat的数据结构,按理我们可以通过Mat.data访问像素数据的指针,再根据指针访问到像素数据,这是最直接的方法,一般图片数据在内存中都是连续存储(一般应该使用is_continues()进行判断,注意上面程序中没有,因为大部分情况是连续存储的,所以没有考虑),这种访问像素方式的一般格式是:
uchar *p;  // 定义一个像素索引指针
p = image.data;  // image为Mat对象,将对象的数据指针赋值给p
for (long i=0; i < image.rows*image.cols*image.channels(); i++) {
    *p++ = ..;  // 通过索引指针操作数据
}

上面程序通过元素指针的方法给出了一个幂次变换的例子:
*(p+i) = (uchar)(255 * 0.5 * ((double)(img.data[i]) / 255) + b);

幂次变换是一种很好用的图像增强的方法,我的Github上还有一个Matlab写的用幂次变换处理外出爬山风景照片的例子(https://github.com/xiahouzuoxin/zx_photo)

2.
基于行指针的访问:OpenCV中定义了一个ptr方法,是一个模板:
// returns pointer to the matrix element
// idx – rows,you should use @isContinues() before decided it
template<int n> uchar* ptr(const Vec<int, n>& idx);

通过ptr(i)直接获得Mat对象的第i行的指针,跟二维数组的行指针有些类似,继而可以通过ptr(i)[j]得到第i行第j列的像素值。

上面程序给出了使用行指针进行图像反转的例子。

3.
请注意一下其它的函数:img.clone()之前已经讲过——除了拷贝Mat数据结构的头和数据指针,连数据也一块拷贝,并将数据指针指向新拷贝的数据。

效果

OpenCV基础篇之像素访问

左边是元素图片,中间是经过图片反转之后的图片,右边是使用幂次变换增强后的图片。

--------------------------------------分割线 --------------------------------------

Ubuntu Linux下安装OpenCV2.4.1所需包

Ubuntu 12.04 安装 OpenCV2.4.2

CentOS下OpenCV无法读取视频文件

Ubuntu 12.04下安装OpenCV 2.4.5总结

Ubuntu 10.04中安装OpenCv2.1九步曲

基于QT和OpenCV的人脸识别系统

--------------------------------------分割线 --------------------------------------

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/f13d6039d20fe66b658a19abc0d8e296.html