首页 > 其他分享 >04 图像像素的读写操作

04 图像像素的读写操作

时间:2023-01-12 09:55:39浏览次数:70  
标签:04 读写操作 int image 像素 255 col row

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      <---------------修改的程序
	
};	

c3dc773259532bc3219105032c69aab

80d9fc342337323049e6a85dc9ac70d

案例讲解

//函数定义
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 >

2e7dc8619a047e7b4953e671f8ec83d

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;

2e7dc8619a047e7b4953e671f8ec83d

标签:04,读写操作,int,image,像素,255,col,row
From: https://www.cnblogs.com/L707/p/17045593.html

相关文章