C++,OpenCV-图像像素读写操作(5)
  Jk5625xsZPHl 2023年11月02日 41 0

常用类型介绍

  • 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);
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  gBkHYLY8jvYd   2023年12月06日   48   0   0 #includecii++
  gBkHYLY8jvYd   2023年11月19日   27   0   0 #includecic++
  gBkHYLY8jvYd   2023年12月09日   29   0   0 cii++数据
  gBkHYLY8jvYd   2023年12月06日   23   0   0 cii++依赖关系
  ZXL8ALkrtBPG   2023年12月06日   21   0   0 字面量c++
  gBkHYLY8jvYd   2023年11月19日   20   0   0 #includei++数据
  lh6O4DgR0ZQ8   2023年11月24日   17   0   0 cii++c++
  gBkHYLY8jvYd   2023年11月19日   21   0   0 i++测试数据数据
  gBkHYLY8jvYd   2023年11月22日   22   0   0 ioscii++
  gBkHYLY8jvYd   2023年12月10日   22   0   0 #include数组i++
  ZXL8ALkrtBPG   2023年11月12日   29   0   0 c++
  gBkHYLY8jvYd   2023年12月08日   20   0   0 #includecii++
  gBkHYLY8jvYd   2023年11月19日   24   0   0 十进制高精度c++
  gBkHYLY8jvYd   2023年11月14日   27   0   0 #includei++升序
  gBkHYLY8jvYd   2023年12月11日   18   0   0 cic++最小值
  gBkHYLY8jvYd   2023年11月19日   22   0   0 测试点cic++
Jk5625xsZPHl