OpenCV图像处理学习四,像素的读写操作和图像反差函数操作

一.读写图像
imread 可以指定加载为灰度或者RGB图像
Imwrite 保存图像文件,类型由扩展名决定


二.读写像素
读一个GRAY(灰度图)像素点的像素值(CV_8UC1)
Scalar intensity = img.at(y, x);
或者 Scalar intensity = img.at(Point(x, y));

读一个RGB像素点的像素值
Vec3f intensity = img.at(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];

三.修改像素值
灰度图像 img.at(y, x) = 128;

RGB三通道图像
img.at(y,x)[0]=128; // blue
img.at(y,x)[1]=128; // green
img.at(y,x)[2]=128; // red

空白图像赋值
img = Scalar(0);

=================================================================

四.图像数据类型区分

Vec3b与Vec3F数据类型的区别
Vec3b对应三通道的顺序是blue、green、red的uchar类型数据。
Vec3f对应三通道的float类型数据

typedef Vec<uchar, 2> Vec2b;//像素的数据值由两个数组成,这两个数的数据类型为uchar
typedef Vec<uchar, 3> Vec3b;//像素的数据值由三个数组成,这三个数的数据类型为uchar
typedef Vec<uchar, 4> Vec4b;//像素的数据值由四个数组成,这四个数的数据类型为uchar
 
typedef Vec<short, 2> Vec2s;//像素的数据值由两个数组成,这两个数的数据类型为short
typedef Vec<short, 3> Vec3s;//像素的数据值由三个数组成,这三个数的数据类型为short
typedef Vec<short, 4> Vec4s;//像素的数据值由四个数组成,这四个数的数据类型为short
 
typedef Vec<ushort, 2> Vec2w;//像素的数据值由两个数组成,这两个数的数据类型为ushort
typedef Vec<ushort, 3> Vec3w;//像素的数据值由三个数组成,这三个数的数据类型为ushort
typedef Vec<ushort, 4> Vec4w;//像素的数据值由四个数组成,这四个数的数据类型为ushort
 
typedef Vec<int, 2> Vec2i;//像素的数据值由两个数组成,这两个数的数据类型为int
typedef Vec<int, 3> Vec3i;//像素的数据值由三个数组成,这三个数的数据类型为int
typedef Vec<int, 4> Vec4i;//像素的数据值由四个数组成,这四个数的数据类型为int
typedef Vec<int, 6> Vec6i;//像素的数据值由六个数组成,这六个数的数据类型为int
typedef Vec<int, 8> Vec8i;//像素的数据值由八个数组成,这八个数的数据类型为int
 
typedef Vec<float, 2> Vec2f;//像素的数据值由两个数组成,这两个数的数据类型为float
typedef Vec<float, 3> Vec3f;//像素的数据值由三个数组成,这三个数的数据类型为float
typedef Vec<float, 4> Vec4f;//像素的数据值由四个数组成,这四个数的数据类型为float
typedef Vec<float, 6> Vec6f;//像素的数据值由六个数组成,这六个数的数据类型为float
 
typedef Vec<double, 2> Vec2d;//像素的数据值由两个数组成,这两个数的数据类型为double
typedef Vec<double, 3> Vec3d;//像素的数据值由三个数组成,这三个数的数据类型为double
typedef Vec<double, 4> Vec4d;//像素的数据值由四个数组成,这四个数的数据类型为double
typedef Vec<double, 6> Vec6d;//像素的数据值由六个数组成,这六个数的数据类型为double

把CV_8UC1转换到CV32F1实现如下:
src.convertTo(dst, CV_32F);

=================================================================

对图像灰度转换,灰度图反差,RGB图像反差等功能代码实现如下:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

//只对灰度图像进行反差并在窗口显示
void grayInvert(Mat &gray);//输入单通道灰度图像

//既可以对彩色图像进行反差,也可以对灰度图像进行反差
void invertImage(Mat &src, Mat &dst);//输入一个图片(三通道或单通道都可),输出dst反差图像

//自定义将rgb彩色图像变为单通道灰度图像(其内方法很多)
void imageToGray(Mat &src, Mat &dst);//输入一个三通道图像,输出单通道灰度图像

int main(){
	Mat src;
	src = imread("1.jpg");//此处默认读进来BGR的图像(有三个通道的值)
	if (!src.data){
		printf("could not load image...\n");
		return -1;
	}
	//img.at<uchar>(y, x);获得单通道的图像才能去读

	namedWindow("input image", CV_WINDOW_AUTOSIZE);//此处可以省略
	imshow("input image", src);

	Mat gray;
	cvtColor(src, gray, CV_RGB2GRAY);//此时将rgb图像转变为灰度图像
	namedWindow("cvtColor gray image", CV_WINDOW_AUTOSIZE);//此处可以省略
	imshow("cvtColor gray image", gray);
	imwrite("cvtColor_gray.jpg", gray);

	grayInvert(gray);//只对灰度图像进行反差并在窗口显示

	//调用自定义函数对图像进行反差
	Mat dst;//定义dst反差图像
	invertImage(src, dst);	//既可以对彩色图像进行反差,也可以对灰度图像进行反差(对上面的grayInvert进一步优化)
	imshow("invertImage image", dst);	//将输出的dst图像进行显示
	imwrite("invertImage.jpg", dst);

	//调用系统自带的图像反差函数(与上方自定义反差功能相同,单通道、三通道都可)
	//此函数是进行位操作(与、或、非等)来对图像反差
	Mat dst2;	//定义dst2作为后面函数的输出
	bitwise_not(src, dst2);
	imshow("bitwise_not image", dst2);
	imwrite("bitwise_not.jpg", dst2);

	//调用自定义rgb转灰度函数(灰度读图像可亮可暗)
	Mat gray2;
	imageToGray(src, gray2);
	imshow("imageToGray image", gray2);
	imwrite("imageToGray2.jpg", gray2);

	waitKey(0);
	return 0;
}

//只对灰度图像进行反差并在窗口显示
void grayInvert(Mat &gray){
	int height = gray.rows;//获取灰度图像的高度
	int width = gray.cols;//获取灰度图像的宽度

	//单通道灰度图像
	for (int row = 0; row < height; row++){
		for (int col = 0; col < width; col++){
			int grayValue = gray.at<uchar>(row, col);//获取灰度图像的像素值
			gray.at<uchar>(row, col) = (255 - grayValue);		//修改gray图像本身的像素值,将其像素进行反差
		}
	}
	imshow("gray invert", gray);	//在3.0.0版本上,不用namewindows窗口,只imshow它就可以自动创建一个窗口展示
	//imshow("gray image", gray);		//如果找到前面有创建窗口,就不再自动创建,直接在之前创建的窗口显示
	imwrite("gray_invert.jpg", gray);
}

//既可以对彩色图像进行反差,也可以对灰度图像进行反差
void invertImage(Mat &src, Mat &dst){
	//创建一个和src大小类型相同的背景图像,并将反差像素在此图像上显示
	dst.create(src.size(), src.type());

	int height = src.rows;//获取src图像的高度
	int width = src.cols;//获取src图像的宽度
	int nc = src.channels();//获取src图像的通道数

	//直接遍历图像像素,并通过判断通道数来进行读取像素的操作(单通道和三通道读取像素操作不同)
	for (int row = 0; row < height; row++){
		for (int col = 0; col < width; col++){
			if (nc == 1){		//如果图像为单通道数进行下列操作
				int grayValue = src.at<uchar>(row, col);		//获取单通道图像的像素值
				dst.at<uchar>(row, col) = (255 - grayValue);		//修改单通道图像本身的像素值,将其像素进行反差
			}
			else if (nc == 3){		//如果图像为三通道
				int b = src.at<Vec3b>(row, col)[0];			//获取r通道的像素值
				int g = src.at<Vec3b>(row, col)[1];			//获取g通道的像素值
				int r = src.at<Vec3b>(row, col)[2];			//获取b通道的像素值
				//将各个通道的反差像素在dst图像上显示
				dst.at<Vec3b>(row, col)[0] = 255 - b;		//我们可以更改一些像素值,会得到其他效果如将(255-r)改为0等像素值
				dst.at<Vec3b>(row, col)[1] = 255 - g;
				dst.at<Vec3b>(row, col)[2] = 255 - r;
			}
		}
	}
	//imshow("dst invert", dst);
}

//自定义将rgb彩色图像变为单通道灰度图像(其内方法很多)
void imageToGray(Mat &src, Mat &dst){
	//创建一个和src大小相同,但类型为单通道的背景图像
	dst.create(src.size(), CV_8UC1);

	int height = src.rows;//获取src图像的高度
	int width = src.cols;//获取src图像的宽度
	int nc = src.channels();//获取src图像的通道数

	//直接遍历图像像素,并通过判断通道数来进行读取像素的操作(单通道和三通道读取像素操作不同)
	for (int row = 0; row < height; row++){
		for (int col = 0; col < width; col++){
			if (nc == 1){		//如果图像为单通道数进行下列操作
				cout << "此为单通道图像,无需再次灰度化" << endl;
			}
			else if (nc == 3){		//如果图像为三通道
				int b = src.at<Vec3b>(row, col)[0];			//获取r通道的像素值
				int g = src.at<Vec3b>(row, col)[1];			//获取g通道的像素值
				int r = src.at<Vec3b>(row, col)[2];			//获取b通道的像素值
				//通过获取的bgb各通道的像素值进行灰度化操作(做灰度的方法很多)
				//dst.at<uchar>(row, col) = min(b, min(g, r));//取rgb通道中的最小值赋值给单通道像素(此处的灰度图像显示会比较暗)
				dst.at<uchar>(row, col) = max(b, max(g, r));//取rgb通道中的最大值赋值给单通道像素(此处的灰度图像显示会比较亮)
			}
		}
	}
	//imshow("imageToGray", dst);
}

代码中函数简介
自定义函数
1. void grayInvert(Mat &gray);
功能:只对单通道灰度图像进行反差操作,内含显示及存储功能
参数1:输入单通道灰度图像

2. void invertImage(Mat &src, Mat &dst);
功能:既可以对彩色图像进行反差,也可以对灰度图像进行反差(与opencv自带的一个函数bitwise_not功能相同,只是此处对图片像素值的操作不是二进制的操作)
参数1:输入一个图片(三通道或单通道都可)
参数2:输出dst反差图像

3. void imageToGray(Mat &src, Mat &dst);
功能:将rgb彩色图像变为单通道灰度图像(在其内转成灰度图像的方式较多,灰度图像有亮有暗)
参数1:输入一个三通道图像
参数2:输出单通道灰度图像

opencv自带函数
1. cvtColor(src, gray, CV_RGB2GRAY);
参数1:输入图像(此处应输入rgb三通道图像)
参数2:输出图像(此处输出单通道灰度图像)
参数3:此处使用CV_RGB2GRAY,表示将读入的rgb彩色图像变为gray灰度图像

2. bitwise_not(src, dst2);
功能:是对二进制数据进行“非”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制 “非” 操作,~1 = 0,~0=1
参数1:输入一个图片(单通道或三通道都可)
参数2:输出像素值被二进制“非”过的图像

=================================================================

图像效果

猜你喜欢

转载自blog.csdn.net/weixin_44651073/article/details/126238788