Mat Mat::row(int i) constios
Mat Mat::col(int j) constdom
Range(start,end);函數
Range::all(); // 表示全部行或列spa
Mat A; Mat B=A(Range::(5,9),Range(1,3)); //表示5-9行(不包括9),1-3列(不包括3)
//在圖像的右下角定義一個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));
使用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; }
注意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; }
迭代器訪問有點像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; }
//用Mat_模板操做圖像 cv::Mat_<uchar> im2(image); im2(50,100)=0; // 訪問第50行,第100列處那個值
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; }
//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; } } }
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; } }
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; }