0
点赞
收藏
分享

微信扫一扫

OpenCV图像像素读写操作

常用类型介绍

  • uchar类型

typedef unsigned uint;
typedef signed char schar;
typedef unsigned char uchar;
typedef unsigned short ushort;

Vec系列

Vec+数字+字母: C++STL vector容器类似

  • 数字: Vec 的长度
  • 字母: 类型
  • b: uchar
  • s:short
  • w: ushort
  • i: int
  • f:float
  • d:double

typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;

typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;

typedef Vec<ushort, 2> Vec2w;
typedef Vec<ushort, 3> Vec3w;
typedef Vec<ushort, 4> Vec4w;

typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<int, 6> Vec6i;
typedef Vec<int, 8> Vec8i;

typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;

typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

图像的像素读写

数组方式读写

int dims = img.channels();		//得到图片通道数
for (int i = 0; i < img.rows; i++) 
{
	for (int j = 0; j < img.cols; j++) 
	{
		if (dims == 1) 
		{
			//单通道图像像素点获取
			int pixel = img.at<uchar>(i, j);
			img.at<uchar>(i, j) = 255 - pixel;		//负片处理
		}
		if (dims == 3) 
		{
			//三通道图像像素点获取
			Vec3b bgr = img.at<Vec3b>(i, j);
			//负片处理
			img.at<Vec3b>(i, j)[0] = 255 - bgr[0];
			img.at<Vec3b>(i, j)[1] = 255 - bgr[1];
			img.at<Vec3b>(i, j)[2] = 255 - bgr[2];
		}
	}
}

指针方式读写

//二维数组-->一级指针访问二维数组方式
int dims = img.channels();
for (int i = 0; i < img.rows; i++) 
{
	//Mat中有一个ptr成员函数,获取当前i行的指针
	uchar* current_row = img.ptr<uchar>(i);
	for (int j = 0; j < img.cols; j++) 
	{
		if (dims == 1) 
		{
			int pixel = *current_row;	   //current_row[j];
			*current_row++ = 255 - pixel;  //做一个横向移动
		}
		if (dims == 3)
		{
			Vec3b bgr = img.at<Vec3b>(i, j);
			*current_row++ = 255 - *current_row;
			*current_row++ = 255 - *current_row;
			*current_row++ = 255 - *current_row;
		}
	}
}

完整案例

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
class ImgVisitPixel 
{
public:
	ImgVisitPixel(int type = IMREAD_UNCHANGED) :img(imread("mm.jpg",type)) {}
	void Show(string wName) 
	{
		imshow(wName, img);
		moveWindow(wName, 600, 300);
		waitKey(0);
	}
	void Visit_By_Array();
	void Visit_By_Point();
protected:
	Mat img;
};

void ImgVisitPixel::Visit_By_Array()
{
	int dims = img.channels();		//得到图片通道数
	for (int i = 0; i < img.rows; i++) 
	{
		for (int j = 0; j < img.cols; j++) 
		{
			if (dims == 1) 
			{
				//单通道图像像素点获取
				int pixel = img.at<uchar>(i, j);
				img.at<uchar>(i, j) = 255 - pixel;		//负片处理
			}
			if (dims == 3) 
			{
				//三通道图像像素点获取
				Vec3b bgr = img.at<Vec3b>(i, j);
				//负片处理
				img.at<Vec3b>(i, j)[0] = 255 - bgr[0];
				img.at<Vec3b>(i, j)[1] = 255 - bgr[1];
				img.at<Vec3b>(i, j)[2] = 255 - bgr[2];
			}
		}
	}
}

void ImgVisitPixel::Visit_By_Point()
{
	int dims = img.channels();
	for (int i = 0; i < img.rows; i++) 
	{
		//Mat中有一个ptr成员函数,获取当前i行的指针
		uchar* current_row = img.ptr<uchar>(i);
		for (int j = 0; j < img.cols; j++) 
		{
			if (dims == 1) 
			{
				int pixel = *current_row;	   //current_row[j];
				*current_row++ = 255 - pixel;  //做一个横向移动
			}
			if (dims == 3)
			{
				Vec3b bgr = img.at<Vec3b>(i, j);
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
			}
		}
	}

}

int main() 
{
	ImgVisitPixel* pImg = new ImgVisitPixel;
	pImg->Show("原图");
	pImg->Visit_By_Array();
	pImg->Show("第一次负片操作");
	pImg->Visit_By_Point();
	pImg->Show("第二次负片操作");
	return 0;
}

像素读写注意点

在读取到像素点的时候,做一些算数运算,一定要注意颜色范围问题,小心溢出,针对溢出,opencv提供一个转换防止溢出

saturate_cast<要转换的类型>(要转换的数据)

  • 小于0 等于0
  • 大于255 直接等于255

img.at<Vec3b>(i, j)[0] =saturate_cast<uchar>(bgr[0]+100);
img.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(bgr[1] + 100);
img.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(bgr[2] + 100);

举报

相关推荐

0 条评论