04 图像像素的读写操作

Posted 柒月的风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了04 图像像素的读写操作相关的知识,希望对你有一定的参考价值。

04 图像像素的读写操作

opencv知识点:

  • 获取/改变图像的某个像素 - Mat::at
  • 图像像素 - 数组遍历
  • 图像像素 - 指针遍历

本课所解决的问题:

  • 如何获取/改变图像的某个像素?

  • 如何利用数组遍历图像像素?

  • 如何利用指针遍历图像像素?

1.获取某个像素

我们获取/改变图像的某个像素,要用到Mat::at< >( )

image.at<uchar>(row, col);
/*
获取指定位置的像素值

这里只是at方法的一种演示,一共6种传参方式,具体可查看文档
说明:
	at<>中必须标明矩阵的数据类型,一般图像是uchar(8位无符号整型)类型
	这里我们采用二维度坐标的方式传参
*/

2.图像像素的数组遍历

为了演示图像像素遍历,我们在遍历的同时进行一个反色处理

程序

main.cpp

#include "opencv2/opencv.hpp"
#include "quickopencv.h"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv) 
	Mat src = imread("C:/Users/LZQ/Desktop/lena.png"); //  B, G, R
	if (src.empty()) 
		printf("could not load image....\\n");
		return -1;
	

	imshow("输入窗口", src);

	QuickDemo qd;


	qd.pixel_visit_demo(src);  //04     <-------------修改的代码(其余不变)

	waitKey(0);
	destroyAllWindows();
	return 0;

quickdemo.cpp

#include "quickopencv.h"
#include <opencv2/dnn.hpp>

using namespace cv;
using namespace std;
/*****************************************************************/
void QuickDemo::pixel_visit_demo(Mat& image) 
	int w = image.cols;           //宽度
	int h = image.rows;           //高度
	int dims = image.channels();  //通道数
	
	for (int row = 0; row < h; row++) 
		for (int col = 0; col < w; col++) 
		
/********************************灰度图像*********************************/
			if (dims == 1)  // 灰度图像
				int pv = image.at<uchar>(row, col);       //pv当前的图像   uchar字节类型
				image.at<uchar>(row, col) = 255 - pv;     //255-pv  反色
			

/********************************彩色图像*********************************/
			if (dims == 3)  // 彩色图像
				Vec3b bgr = image.at<Vec3b>(row, col);      //(行,列)  可以将Vec3b bgr看为一个数组
				
				image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
				image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
				image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
			
/*****************************************************************/			
		
	
    
	imshow("像素读写演示", image);


quickopencv.h

#pragma once

#include <opencv2/opencv.hpp>

using namespace cv;

class QuickDemo             //快速的演示文件 class类
public:

	void pixel_visit_demo(Mat& image);     //04      <---------------修改的程序
	
;	

案例讲解

//函数定义
void pixel_visit_demo(Mat& image);

//函数实现
void QuickDemo::pixel_visit_demo(Mat& image) 

	int h = image.rows;
	int w = image.cols;
	int dims = image.channels();
	/*
		灰度图像——通道为1
		彩色图像——通道为3
	*/
	for(int row = 0; row < h; row++) 
		for (int col = 0; col < w; col++) 
				
			if (dims == 1) //灰度图像
				int pv = image.at<uchar>(row, col);

				image.at<uchar>(row, col) = 255 - pv;
			
			
			if (dims == 3) //彩色图像
				Vec3b bgr = image.at<Vec3b>(row, col);

				image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
				image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
				image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
			
		
	
	imshow("像素读写演示", image);


如上,我们可以看到,不同通道数的处理方式是不同的

  • 对于单通道图像的使用方法:
int pv = image.at<uchar>(row, col);

image.at<uchar>(row, col) = 255 - pv;//对访问的像素进行反色
  • 对于RGB三通道图像的使用方法:
Vec3b bgr = image.at<Vec3b>(row, col);

image.at<Vec3b>(row, col)[0] = 255 - bgr[0];//对访问的像素进行反色
image.at<Vec3b>(row, col)[1] = 255 - bgr[1];//对访问的像素进行反色
image.at<Vec3b>(row, col)[2] = 255 - bgr[2];//对访问的像素进行反色

这里我们解释一下Vec3b是什么

Vec3b可以看作是vector<uchar, 3>。
简单而言就是一个uchar类型的,长度为3的vector向量。

根据通道数的不同,数据类型的不同,就有了很多变化,下面是常用的三种

8U 类型的 RGB 彩色图像可以使用 < Vec3b >
3 通道 float 类型的矩阵可以使用 < Vec3f >
3 通道 int 类型的矩阵可以使用 < Vec3i >

3.图像像素的指针遍历

另一种更快的方式就是指针遍历

通过设置每一行的首地址指针,我们可以实现更快的遍历

quickdemo.cpp

(主函数和头文件保持不变,改变 quickdemofor循环部分)

void QuickDemo::pixel_visit_demo(Mat& image) 
	int w = image.cols;           //宽度
	int h = image.rows;           //高度
	int dims = image.channels();  //通道数

以上的部分保持不变。

下面的部分是demo的修改重点。

for(int row = 0; row < h; row++) 

		uchar* curren_row = image.ptr<uchar>(row);
		//相当于每次获取行的首地址
		for (int col = 0; col < w; col++) 
			
			//灰度图像
			if (dims == 1) 
				*curren_row++ = 255 - *curren_row;
			
			//彩色图像
			if (dims == 3) 
				*curren_row++ = 255 - *curren_row;
				*curren_row++ = 255 - *curren_row;
				*curren_row++ = 255 - *curren_row;
			
		
	

取完每行的首地址之后

  • 对于单通道图像的使用方法:
*curren_row++ = 255 - pv;
  • 对于RGB三通道图像的使用方法:
//与数组遍历相比,3通道时执行三次就可以
*curren_row++ = 255 - *curren_row;
*curren_row++ = 255 - *curren_row;
*curren_row++ = 255 - *curren_row;

以上是关于04 图像像素的读写操作的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 读写图像读写像素修改像素值(案例:图像反处理)

OpenCV之图像像素读写

进行画布图像像素操作的步骤是啥?

opencv4opencv视频教程 C++ 5读写图像imreadimwrite读写像素at<>()修改像素值ROI区域选择(图像裁剪)RectVec3b与Vec3FCV_32F)

C/C++ vs2017 OpenCV简单入门

C/C++ vs2017 OpenCV简单入门