一、AT函数定义
AT函数是OPENCV中重要的函数之一,它的作用是修改Mat的矩阵某个像素值。换言之,我们需要修改图像中的像素点就需要利用AT函数去获取并且修改,AT函数的修改一般需要循环cols和rows然后对每个像素点进行修改,如上图。AT函数的定义如下:
at<typename>(int i, int j)
第一个参数:typename指的是OPENCV的向量类型,向量类型如下:
typedef Vec<uchar, 2> Vec2b:uchar类型的数组,长度为2, 它表示的是二维图像的位置信息、尺寸等等
typedef Vec<uchar, 3> Vec3b:uchar类型的数组,长度为3,它常用于彩色图像的像素值以及对rgb三个通道的处理,并且通道的像素值都是uchar类型
typedef Vec<uchar, 4> Vec4b:uchar类型的数组,长度为4,它常用于彩色图像的像素值以及对argb四个通道的处理,并且通道的像素值都是uchar类型
typedef Vec<short, 2> Vec2s:short类型的数组,长度为2, 它表示的是二维图像的位置信息、尺寸等等,但不能做像素处理
typedef Vec<short, 3> Vec3s:short类型的数组,长度为3, 它常用于彩色图像的像素值以及对rgb三个通道的处理,并且通道的像素值都是short类型
typedef Vec<short, 4> Vec4s:short类型的数组,长度为4, 它常用于彩色图像的像素值以及对argb四个通道的处理,并且通道的像素值都是short类型
typedef Vec<ushort, 2> Vec2w:ushort类型的数组,长度为2,它表示的是二维图像的位置信息、尺寸等等,但不能做像素处理
typedef Vec<ushort, 3> Vec3w:ushort类型的数组,长度为3,它常用于彩色图像的像素值以及对rgb三个通道的处理,并且通道的像素值都是ushort类型
typedef Vec<ushort, 4> Vec4w:ushort类型的数组,长度为4,它常用于彩色图像的像素值以及对argb四个通道的处理,并且通道的像素值都是ushort类型
typedef Vec<int, 2> Vec2i:int类型的数组,长度为2, 它表示的是一个包含2个整数的元素向量,并不能直接表示通道数
typedef Vec<int, 4> Vec4i:int类型的数组,长度为4, 它常用于彩色图像的像素值以及对argb四个通道的处理,并且通道的像素值都是int类型
typedef Vec<int, 6> Vec6i:int类型的数组,长度为6, 它常用于表示六维图像,包括:坐标、描述子、颜色直方等等,但是不能对六维图像直接进行处理
typedef Vec<int, 8> Vec8i:int类型的数组,长度为8, 它常用于表示八维图像,包括:坐标、描述子、颜色直方等等,但是不能对八维图像直接进行处理
typedef Vec<float, 2> Vec2f:float类型的数组,长度为2,它表示的是二维图像的位置信息,但不能做通道处理
typedef Vec<float, 3> Vec3f:float类型的数组,长度为3,它常用于彩色图像的像素值以及对rgb三个通道的处理,并且通道的像素值都是浮点数
typedef Vec<float, 4> Vec4f:float类型的数组,长度为4,它常用于彩色图像的像素值以及对argb四个通道的处理,并且通道的像素值都是浮点数
typedef Vec<float, 6> Vec6f:float类型的数组,长度为4,他用于处理6个维度的图像数据,需要注意的是Vec6f仅仅能表示具有6个维度的数据,并不可以对数据进行操作.
typedef Vec<double, 2> Vec2d:double类型的数组,长度为2,在图像处理中Vec2d仅仅只是表示具有double类型的图像数据,但是并不能直接操作数据像素
typedef Vec<double, 3> Vec3d:double类型的数组,长度为3,它常用于表示图像的彩色三通道,分别是R(红色)、G(绿色)、B(蓝色),并且对于这三个通道的像素值进行double类型数据的处理
typedef Vec<double, 4> Vec4d:double类型的数组,长度为4,它常用于表示图像的彩色四通道,分别是A(透明度)、R(红色)、G(绿色)、B(蓝色),并且对于这四个通道的像素值进行double类型数据的处理。
需要注意的是:一般OPENCV对像素的处理大部分都是用uchar类型,其他类型用的很少。
第二个参数:i,指的是rows,图像的行数据
第三个参数:j,指的是cols,图像的列数据
二、代码实现at函数遍历Mat矩阵的像素点,并修改像素
#include <opencv2/opencv.hpp> #include <opencv2/dnn.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace std; using namespace cv; int main() { Mat mat = imread("frame1.jpg"); for(int i = 0;i < mat.rows; i++) { for(int j = 0;j < mat.cols; j++) { mat.at<Vec3b>(i,j)[0] = (int)mat.at<Vec3b>(i,j)[0] - 10; //对第一个通道进行像素处理 mat.at<Vec3b>(i,j)[1] = (int)mat.at<Vec3b>(i,j)[1] - 50; //对第二个通道进行像素处理 mat.at<Vec3b>(i,j)[2] = (int)mat.at<Vec3b>(i,j)[2] - 10; //对第三个通道进行像素处理 } } imwrite("frame1_process.jpg", mat); Mat before_process_gray_Image; Mat process_gray_Image; cvtColor(mat, before_process_gray_Image, COLOR_RGB2GRAY); cvtColor(mat, process_gray_Image, COLOR_RGB2GRAY); for(int i = 0;i< process_gray_Image.rows;i++) { for(int j = 0;j<process_gray_Image.cols;j++) { process_gray_Image.at<uchar>(i,j) = 50 - (int)process_gray_Image.at<uchar>(i,j); } } imwrite("gray_frame1.jpg", before_process_gray_Image); imwrite("gray_frame1_process.jpg", process_gray_Image); return 0; }2.1彩色图像素通道调整
本章节代码主要是实现对一个Mat矩阵用at函数去遍历cols和rows,并修改三通道像素(这里的像素是三通道图像数据),
int main() { // 读取当前目录下的frame1.jpg彩色图片,默认以BGR三通道格式加载到mat中 Mat mat = imread("frame1.jpg"); // 外层循环:遍历图像每一行(y轴,行号i从0到mat.rows-1) for(int i = 0;i < mat.rows; i++) { // 内层循环:遍历当前行的每一列(x轴,列号j从0到mat.cols-1) for(int j = 0;j < mat.cols; j++) { // 访问第i行第j列像素的第0通道(B蓝色通道),像素值减10后重新赋值 mat.at<Vec3b>(i,j)[0] = (int)mat.at<Vec3b>(i,j)[0] - 10; // 访问第1通道(G绿色通道),像素值减50后重新赋值 mat.at<Vec3b>(i,j)[1] = (int)mat.at<Vec3b>(i,j)[1] - 50; // 访问第2通道(R红色通道),像素值减10后重新赋值 mat.at<Vec3b>(i,j)[2] = (int)mat.at<Vec3b>(i,j)[2] - 10; } } // 将处理后的彩色图像保存为frame1_process.jpg imwrite("frame1_process.jpg", mat);frame1.jpg:是没有处理处理的图像
frame1_process.jpg:是经过像素处理过后的图像,可以看到经过处理后,图像变成了绿色
2.2 灰度图转换与像素处理
// 定义两个灰度图Mat对象 Mat before_process_gray_Image; Mat process_gray_Image; // 将处理后的彩色图mat转为灰度图,赋值给before_process_gray_Image cvtColor(mat, before_process_gray_Image, COLOR_RGB2GRAY); // 重复将同一张mat转为灰度图,赋值给process_gray_Image cvtColor(mat, process_gray_Image, COLOR_RGB2GRAY); // 遍历灰度图的每一个像素 for(int i = 0;i< process_gray_Image.rows;i++) { for(int j = 0;j<process_gray_Image.cols;j++) { // 灰度像素值 = 50 - 原像素值 process_gray_Image.at<uchar>(i,j) = 50 - (int)process_gray_Image.at<uchar>(i,j); } }gray_frame1.jpg :没有经过像素处理的灰度jpg图片
gray_frame1_process.jpg :经过像素处理后的Jpg图片