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數據結構的頭和數據指針,連數據也一塊拷貝,並將數據指針指向新拷貝的數據。
效果
左邊是元素圖片,中間是經過圖片反轉之後的圖片,右邊是使用冪次變換增強後的圖片。
--------------------------------------分割線 --------------------------------------
Ubuntu Linux下安裝OpenCV2.4.1所需包 http://www.linuxidc.com/Linux/2012-08/68184.htm
Ubuntu 12.04 安裝 OpenCV2.4.2 http://www.linuxidc.com/Linux/2012-09/70158.htm
CentOS下OpenCV無法讀取視頻文件 http://www.linuxidc.com/Linux/2011-07/39295.htm
Ubuntu 12.04下安裝OpenCV 2.4.5總結 http://www.linuxidc.com/Linux/2013-06/86704.htm
Ubuntu 10.04中安裝OpenCv2.1九步曲 http://www.linuxidc.com/Linux/2010-09/28678.htm
基於QT和OpenCV的人臉識別系統 http://www.linuxidc.com/Linux/2011-11/47806.htm
--------------------------------------分割線 --------------------------------------