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)

二.区域访问

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)(指针在高的第一行)

                      再访问列(内循环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;  //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;
}
原文地址:https://www.cnblogs.com/k5bg/p/11077032.html