OpenCV2:幼儿园篇 第四章 访问图像
一.行/列訪問
1.單行/單列訪問
Mat Mat::row(int i) const
Mat Mat::col(int j) const
2.多行/多列訪問
Range(start,end);
Range::all();? // 表示所有行或列
Mat A; Mat B=A(Range::(5,9),Range(1,3)); //表示5-9行(不包括9),1-3列(不包括3)?
二.區(qū)域訪問
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()函數必須用兩個循環(huán)實現
注意訪問順序,先訪問行(外循環(huán)rows)(指針在高的第一行)
????????????????????? 再訪問列(內循環(huán)cols)(指針移動寬的每一行)
?
template <typename _Tp> inline _Tp& Mat::at(int i0, int i1)
template <typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const
?
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; //Bluepixel[1] = j%255; //Greenpixel[2] = 0; //Redcolorim.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()函數都需要兩個循環(huán)來遍歷像素.雖然它返回的是指針,索引速度比較快,但是指針不進行類型以及越界檢查
它的訪問順序是跟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; //Bluep[j][1] = j%255; //Greenp[j][2] = 0; //Red}}imshow("grayim", grayim);imshow("colorim", colorim);cv::waitKey(0);return 0; }?
3.迭代器訪問
迭代器訪問有點像at()函數訪問,雖然它只需要一個循環(huán),但是它的可讀性沒有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 反色tableuchar 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.cppvoid 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>();//循環(huán)遍歷所有像素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]]);}}//把未處理的像素設為0result.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; }?
轉載于:https://www.cnblogs.com/k5bg/p/11077032.html
總結
以上是生活随笔為你收集整理的OpenCV2:幼儿园篇 第四章 访问图像的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 跨IP拷贝命令 scp
- 下一篇: 关于线程池,那些你还不知道的事