OpenCV2:幼兒園篇 第四章 訪問圖像

一.行/列訪問

1.單行/單列訪問

Mat Mat::row(int i) constios

Mat Mat::col(int j) constdom

2.多行/多列訪問

Range(start,end);函數

Range::all();  // 表示全部行或列spa

Mat A;
Mat B=A(Range::(5,9),Range(1,3));  //表示5-9行(不包括9),1-3列(不包括3)

 

二.區域訪問

1.CRect

//在圖像的右下角定義一個ROI
cv::Mat imageROI(image,cv::Rect(image.cols-logo.cols,
                                image.rows-logo.rows,
                                logo.cols,
                                logo.rows));
 
 
或者
cv::Mat imageROI=image(cv::Rect(image.cols-logo.cols,
                                image.rows-logo.rows,
                                logo.cols,
                                logo.rows));

 

2.CSize

 

三.像素訪問

1.at()訪問

使用at()函數代碼可讀性高,效率不是很高,使用at()函數必須用兩個循環實現指針

注意訪問順序,先訪問行(外循環rows)(指針在高的第一行)blog

                      再訪問列(內循環cols)(指針移動寬的每一行)索引

 

template <typename _Tp> inline _Tp& Mat::at(int i0, int i1)it

template <typename _Tp> inline const _Tp& Mat::at(int i0, int i1) constio

 

template <typename _Tp> inline _Tp& Mat::at(Point pt)圖像處理

template <typename _Tp> inline const _Tp& Mat::at(Point pt) const

 

template <typename _Tp> inline _Tp& Mat::at(int i0)

template <typename _Tp> inline const _Tp& Mat::at(int i0) const

 

template <typename _Tp> inline _Tp& Mat::at(int i0, int i1, int i2)

template <typename _Tp> inline const _Tp& Mat::at(int i0, int i1, int i2) const

 

template <typename _Tp> inline _Tp& Mat::at(const int* idx)

template <typename _Tp> inline const _Tp& Mat::at(const int* idx) const

 

template <typename _Tp, int n> _Tp& Mat::at(const Vec<int, n>& idx)

template <typename _Tp, int n> inline const _Tp& Mat::at(const Vec<int, n>& idx) const

 

at()函數是模板函數,能夠自定義類型

其中at<uchar>表示單通道圖像,at<cv::Vec3b>表示三通道圖像

 

//遍歷像素值
 
#include <iostream>
#include "opencv2/opencv.hpp"
 
using namespace std;
 
int main(int argc, char* argv[]) {
 
	cv::Mat grayim(600, 800, CV_8UC1);
	cv::Mat colorim(600, 800, CV_8UC3);
 
	//遍歷全部像素,並設置像素值
	for(int i = 0;i < grayim.rows; ++i)
		for(int j = 0; j < grayim.cols; ++j)
			grayim.at<uchar>(i,j) = (i+j)%255;
 
	//遍歷全部像素,並設置像素值
	for(int i=0; i<colorim.rows; ++i)
		for(int j=0; j<colorim.cols; ++j)
		{
 
			cv::Vec3b pixel;
			pixel[0] = i%255;  //Blue
			pixel[1] = j%255;  //Green
			pixel[2] = 0;      //Red
			colorim.at<cv::Vec3b>(i,j) = pixel;
		}
 
	cv::imshow("grayim",grayim);
	cv::imshow("colorim",colorim);
 
	cv::waitKey(0);
 
	return 0;
 
}

 

2.ptr()訪問

注意at()函數返回的是一個uchar變量類型,而ptr()函數返回的是一個uchar*指針類型

ptr()函數和at()函數都須要兩個循環來遍歷像素.雖然它返回的是指針,索引速度比較快,可是指針不進行類型以及越界檢查

它的訪問順序是跟at()函數有點像,先獲取首個行指針,再遍歷列指針

 

inline uchar* Mat::ptr(int y)

inline const uchar* Mat::ptr(int y) const

template<typename _Tp> inline _Tp* Mat::ptr(int y)

template<typename _Tp> inline const _Tp* Mat::ptr(int y) const

 

inline uchar* Mat::ptr(int i0, int i1)

intline const uchar* Mat::ptr(int i0, int i1) const

template<typename _Tp> inline _Tp* Mat::ptr(int i0, int i1)

template<typename _Tp> inline const _Tp* Mat::ptr(int i0, int i1) const

 

inline uchar* Mat::ptr(int i0, int i1, int i2)

inline const uchar* Mat::ptr(int i0, int i1, int i2) const

template<typename _Tp> inline _Tp* Mat::ptr(int i0, int i1, int i2)

template<typenmae _Tp> inline const _Tp* Mat::ptr(int i0, int i1, int i2) const

 

inline uchar* Mat::ptr(const int* idx)

inline const uchar* Mat::ptr(const int* idx) const

 

 

#include <iostream>
#include "opencv2/opencv.hpp"
 
using namespace std;
 
int main(int argc, char* argv[]) {
 
	cv::Mat grayim(600,800,CV_8UC1);
	cv::Mat colorim(600,800,CV_8UC3);
 
	//遍歷全部像素,並設置像素值
	for( int i = 0; i < grayim.rows; ++i) {
 
		//獲取第i行首像素指針
		uchar* p = grayim.ptr<uchar>(i);
 
		//對第i的每一個像素操做
		for(int j = 0;j < grayim.cols; ++j)
			p[j] = (i+j)%255;
	}
 
	//遍歷全部像素,並設置像素值
	for( int i = 0; i<colorim.rows; ++i) {
 
		//獲取第i行首像素指針
		cv::Vec3b* p=colorim.ptr<cv::Vec3b>(i);
		for( int j = 0; j < colorim.cols; ++j) {
			p[j][0] = i%255;  //Blue
			p[j][1] = j%255;  //Green
			p[j][2] = 0;     //Red
		}
	}
 
	imshow("grayim", grayim);
	imshow("colorim", colorim);
	cv::waitKey(0);
 
	return 0;
}

 

3.迭代器訪問

迭代器訪問有點像at()函數訪問,雖然它只須要一個循環,可是它的可讀性沒有at()函數清楚

 

MatIterator_是一個類模板,而at()函數是函數模板

MatIterator_相似於STL中的迭代器,根據迭代器開頭和結尾一直遍歷

 

template<typename _Tp>

class MatIterator_ : public MatConstIterator_<_Tp>

{

public:

  typedef _Tp* pointer;

  typedef _Tp& reference;

  typedef std::random_access_iterator_tag iterator_category;

  

  MatIterator_();

  MatIterator_(Mat_<_Tp>* _m);

  MatIterator_(Mat_<_Tp>* _m, int _row, int _col = 0);

  MatIterator_(const Mat_<_Tp>* _m, Point _pt);

  MatIterator_(const Mat_<_Tp>* _m, const int* _idx);

  MatIterator_(const MatIterator_& it);

  MatIterator_& operator = (const MatIterator_<_Tp>& it);

 

  _Tp& operator *() const;

  _Tp& operator [](ptrdiff_t i) const;

 

  MatIterator_& operator += (ptrdiff_t ofs);

  MatIterator_& operator -= (ptrdiff_t ofs);

  MatIterator_& operator -- ();

  MatIterator_  operator --  (int);

  MatIterator_& operator ++ ();

  MatIterator_  operator ++ (int);

};

 

#include <iostream>
#include "opencv2/opencv.hpp"
 
using namespace std;
 
int main(int argc, char* argv[]) {
 
	cv::Mat grayim(600, 800, CV_8UC1);
	cv::Mat colorim(600, 800, CV_8UC3);
 
	//遍歷全部像素,並設置像素值
	cv::MatIterator_<uchar> grayit, grayend;
 
	for( grayit = grayim.begin<uchar>(), grayend = grayim.end<uchar>(); grayit != grayend; ++grayit)
		*grayit = rand()%255;
 
	//遍歷全部像素,並設置像素值
	cv::MatIterator_<cv::Vec3b> colorit,colorend;
 
	for( colorit = colorim.begin<cv::Vec3b>(), colorend = colorim.end<cv::Vec3b>(); colorit != colorend; ++colorit) {
 
		(*colorit)[0] = rand()%255;  //Blue
		(*colorit)[1] = rand()%255;  //Green
		(*colorit)[2] = rand()%255;  //Red
	}
 
	//顯示結果
	cv::imshow("grayim", grayim);
	cv::imshow("colorim", colorim);
	
	cv::waitKey(0);
 
	return 0;
 
}

 

4.模板訪問

//用Mat_模板操做圖像
cv::Mat_<uchar> im2(image);
im2(50,100)=0;  // 訪問第50行,第100列處那個值

 

5.查找表訪問

LUT(Look Up Table,查找表)是一張像素灰度值的映射表,它將採樣到的灰度值通過圖像處理(替換 反轉  賦值 閾值 二值化 灰度變化等),利用映射關係變換成相應的灰度值

OpenCV中LUT查找表包含256個元素,應用於單通道或相同類型的多通道數據,用於減小圖像映射的時間複雜度

cv::Mat inverseColor6(cv::Mat srcImage)
{

	int row = srcImage.rows;
	int col = srcImage.cols;
	cv::Mat tempImage = srcImage.clone();

	// 創建LUT 反色table
	uchar LutTable[256];
	for (int i = 0; i < 256; ++i)
		LutTable[i] = 256 - i;

	cv::Mat lookUpTable(1, 256, CV_8U);
	uchar* pData = lookUpTable.data;

	// 創建映射表
	for (int i = 0; i <256; ++i)
		pData[i] = LutTable[i];

	// 應用搜索表進行查找
	cv::LUT(srcImage, lookUpTable, tempImage);

	return tempImage;
}

 

四.例子

1.減色

(1)指針
//test.cpp
 
void colorReduce(cv::Mat image,int div=64){
 
	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++){
 
			//處理每一個像素
			data[i]=data[i]/div*div+div/2;
 
		}
		
	}
 
}
 
 (2)迭代器
void colorReduce(cv::Mat image,int div=64){
 
	//在初始位置得到迭代器
	cv::Mat_<cv::Vec3b>::iterator it=image.begin<cv::Vec3b>();
 
	//得到結束位置
	cv::Mat_<cv::Vec3b>::iterator itend=image.end<cv::Vec3b>();
 
	//循環遍歷全部像素
	for(;it!=itend;++it){
 
		//處理每一個像素
		(*it)[0]=(*it)[0]/div*div+div/2;
		(*it)[1]=(*it)[1]/div*div+div/2;	
		(*it)[2]=(*it)[2]/div*div+div/2;
 
	}
 
}

 

2.銳化

void sharpen(const cv::Mat& image,cv::Mat& result){

	//判斷是否須要分配圖像數據,若是須要,就分配
	result.create(image.size(),image.type());
	int nchannels=image.channels();		//得到通道數

	//處理全部行(除了第一行和最後一行)
	for(int j=1;j<image.rows-1;j++){

		const uchar* previous=image.ptr<const uchar>(j-1);  //上一行
		const uchar* current=image.ptr<const uchar>(j);	   //當前行
		const uchar* next=image.ptr<const uchar>(j+1);	   //下一行

		uchar* output=result.ptr<uchar>(j);					//輸出行

		for(int i=nchannels;i<(image.cols-1)*nchannels;i++){

			*output++=cv::saturate_cast<uchar>(
				5*current[i]-current[i-nchannels]-current[i+nchannels-previous[i]-next[i]]);


		}
	}

	//把未處理的像素設爲0
	result.row(0).setTo(cv::Scalar(0));
	result.row(result.rows-1).setTo(cv::Scalar(0));
	result.col(0).setTo(cv::Scalar(0));
	result.col(result.cols-1).setTo(cv::Scalar(0));

}



int main()
{
	

	cv::Mat imag1=cv::imread("a.jpg");
	cv::Mat result;

	sharpen(imag1,result);

	cv::namedWindow("Image");
	cv::imshow("Image",result);


	cv::waitKey(0);

	system("pause");
	return 0;
}
相關文章
相關標籤/搜索