OpenCV Mat对象

本文详细介绍了OpenCV 2.0中Mat对象与IplImage的异同,包括Mat对象的优势、内存管理、构造函数与常用方法。重点讲解了如何通过copyTo和clone函数进行部分或完全复制,并展示了Mat对象的创建、使用要点和实例。

OpenCV Mat对象

Mat对象与IplImage对象

  • Mat对象OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分
  • lpllmage是从2001年OpenCv发布之后就一直存在,是c语言风格的数据结构,需要开发者自己分配与管理内存,对天的程序使用它容易导致内存泄漏问题

Mat对象构造函数与常用方法

常用方法

void copyTo(Mat mat)
void convertTo(Mat dst, int type)
Mat clone()
int channels()
int depth()
bool empty()
uchar* ptr(i=o)

Mat对象使用

  • 部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分
    Mat A= imread(imgFilePath);Mat B(A)//只复制
  • 完全复制:如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现:Mat F = A.clone();或 Mat G; A.copyTo(G);

Mat对象使用-四个要点

  • 输出图像的内存是自动分配的
  • 使用OpenCv的C++接口,不需要考虑内存分配问
  • 题赋值操作和拷贝构造函数只会复制头部分
  • 使用clone与copyTo两个函数实现数据完全复制

Mat对象创建

  • cv::Mat::Mat构造函数
    Mat M(2,2,cV_8uC3, Scalar(0,0,255))
    其中前两个参数分别表示行(row)跟列(column)、第三个.cV_8UC3中的8表示每个通道占8位、u表示无符号、c表示Char类型、3表示通道数自是,第四个参数是向量表示初始化每个像素值是多少,向量长度对应通道数自—致
  • 创建多维数组cv;:Mat::create
int sz[3]={2,2,2};
Mat L(3,sz,cV_8uC1, Scalar::all(0));
  • cv::Mat::create实现
Mat M;
M.create(4,3,CV_8UC2);
M= Scalar(127,127);
cout<< "M = " << endl << " "<<M<<endl << endl;
uchar* firstRow = M.ptr<uchar>(0);
printf( "%d" ,*firstRow);
  • 定义小数组
Mat C = (Mat_<double>(3,3)<<0,-1,O,-1,5,-1,0,-1,0);
cout<< "C= " <<endl<<" " <<C<<endl << endl;

小demo

#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include<iostream>
using namespace cv;

int main(int argc, char** argv)
{
	Mat src = imread("F://1.png", IMREAD_COLOR);
	if (src.empty()) {
		printf("error");
		return -1;
	}
	namedWindow("test opencv setup", CV_WINDOW_AUTOSIZE);
	imshow("test opencv setup", src);

	Mat dst;
	dst = Mat(src.size(), src.type());
	dst = Scalar(123, 213, 12);//色素覆盖创建的Mat对象

	namedWindow("out put window", CV_WINDOW_AUTOSIZE);
	imshow("out put window", dst);
	waitKey(0);
	return 0;
}

输出色素覆盖创建的Mat对象以及原图
在这里插入图片描述

<think> 我们正在解决如何改变OpenCV Mat对象每个像素的RGB值的问题。 根据引用[1][2][3][4],我们知道Mat对象OpenCV中存储图像数据的主要结构,它包含了图像的像素数据。 改变每个像素的RGB值,实际上就是遍历Mat对象的每一个像素,然后修改其BGR(注意OpenCV默认是BGR顺序)三个通道的值。 方法步骤: 1. 确保Mat对象是3通道的彩色图像(如果是灰度图,则没有RGB三个通道)。 2. 遍历图像的每一个像素。 3. 对每个像素,分别修改其B、G、R通道的值。 遍历像素的方法有多种,常见的有: - 使用指针(高效,适合大图像) - 使用迭代器(安全,但效率稍低) - 使用at方法(简单,但效率较低) 下面我们将分别展示这三种方法。 注意:在OpenCV中,三通道图像的每个像素由三个值组成(B、G、R),通常使用Vec3b(8位无符号整数)表示。 示例代码(使用指针): ```cpp #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image = imread("image.jpg"); // 读取图像 if (image.empty()) return -1; // 确保是3通道图像 if (image.channels() != 3) { // 如果不是3通道,可以转换或者报错,这里我们假设是3通道 return -1; } // 使用指针遍历 for (int row = 0; row < image.rows; row++) { // 获取当前行的指针 Vec3b* ptr = image.ptr<Vec3b>(row); for (int col = 0; col < image.cols; col++) { // 修改当前像素的BGR值 // 例如:将每个像素的蓝色通道设为0,绿色和红色保持不变 ptr[col][0] = 0; // B通道置0 // 如果要将红色通道置0,则:ptr[col][2] = 0; // 如果要将绿色通道置0,则:ptr[col][1] = 0; // 也可以进行其他操作,如反色:ptr[col] = Vec3b(255,255,255) - ptr[col]; } } imshow("Result", image); waitKey(0); return 0; } ``` 示例代码(使用迭代器): ```cpp #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image = imread("image.jpg"); if (image.empty()) return -1; // 使用迭代器 MatIterator_<Vec3b> it, end; for (it = image.begin<Vec3b>(), end = image.end<Vec3b>(); it != end; ++it) { // 修改每个像素 (*it)[0] = 0; // 蓝色通道置0 // (*it)[1] = 0; // 绿色通道置0 // (*it)[2] = 0; // 红色通道置0 } imshow("Result", image); waitKey(0); return 0; } ``` 示例代码(使用at方法): ```cpp #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image = imread("image.jpg"); if (image.empty()) return -1; for (int row = 0; row < image.rows; row++) { for (int col = 0; col < image.cols; col++) { // 使用at方法访问像素 Vec3b& pixel = image.at<Vec3b>(row, col); pixel[0] = 0; // B通道置0 // pixel[1] = 0; // G通道置0 // pixel[2] = 0; // R通道置0 } } imshow("Result", image); waitKey(0); return 0; } ``` 以上三种方法都可以实现,其中指针方法效率最高,迭代器安全性好,at方法简单直观。 另外,还可以使用OpenCV提供的LUT(查找表)进行整幅图像的像素值变换,但LUT通常用于每个通道独立的变换,不能实现像素之间的依赖(比如根据邻域像素修改)。 注意:在修改像素时,如果图像是其他类型(比如16UC3),则需要使用Vec3w(16位无符号整数)等对应的类型。 引用[4]中提到了Mat类的创建和基本操作,引用[5]提到了如何打印Mat的像素数据,这可以帮助调试。 总结:改变Mat对象每个像素的RGB值,就是遍历每个像素并修改其三个通道的值。根据需求选择遍历方法。 §§相关问题§§ 1. OpenCVMat对象的常见操作有哪些? 2. 如何高效地遍历OpenCV Mat图像? 3. OpenCV中如何将BGR图像转换为灰度图? 4. 如何使用查找表(LUT)进行像素值的批量修改? </think> ### OpenCV中修改Mat对象每个像素RGB值的方法 在OpenCV中,修改`cv::Mat`对象的像素RGB值主要通过直接访问和操作像素数据实现。以下是三种常用方法,均基于引用[1][2][3][4]的技术原理: --- #### 1. **使用指针高效遍历(推荐大图像处理)** ```cpp #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image = imread("image.jpg"); // 读取BGR图像[^1] if (image.empty()) return -1; for (int row = 0; row < image.rows; row++) { Vec3b* ptr = image.ptr<Vec3b>(row); // 获取行指针[^2] for (int col = 0; col < image.cols; col++) { // 修改RGB值(OpenCV默认BGR顺序) ptr[col][0] = 0; // B通道置0(蓝色归零) ptr[col][1] = 255; // G通道置255(绿色最大) ptr[col][2] *= 0.5; // R通道减半(红色减半) } } imshow("Result", image); waitKey(0); return 0; } ``` - **原理**:通过`ptr<Vec3b>()`直接访问内存连续区域,效率最高[^1] - **Vec3b说明**:三通道无符号字节向量,存储BGR值[^2] - **适用场景**:大型图像处理 --- #### 2. **使用at()方法直接访问(适合小图像或随机访问)** ```cpp Mat image = imread("image.jpg"); for (int row = 0; row < image.rows; row++) { for (int col = 0; col < image.cols; col++) { Vec3b& pixel = image.at<Vec3b>(row, col); // 获取像素引用 pixel[0] = 255 - pixel[0]; // B通道取反(负片效果) pixel[1] = 100; // G通道固定值 } } ``` - **优点**:代码直观,适合随机像素访问 - **注意**:需确保`Mat`类型匹配(此处为`Vec3b`) --- #### 3. **使用迭代器安全遍历(避免越界访问)** ```cpp Mat image = imread("image.jpg"); MatIterator_<Vec3b> it, end; for (it = image.begin<Vec3b>(), end = image.end<Vec3b>(); it != end; ++it) { (*it)[2] = 0; // 红色通道清零(R=0(*it)[1] = (*it)[0]; // 绿色通道复制蓝色值(G=B) } ``` - **特点**:自动处理边界,代码安全性高[^4] - **适用场景**:复杂遍历逻辑 --- #### 关键说明: 1. **通道顺序**:OpenCV默认使用**BGR**排列(非RGB)[^2] 2. **数据类型**: - `Vec3b`:三通道8位无符号整数(0-255) - `Vec3f`:三通道浮点数(需先转换类型) 3. **预检查**: ```cpp if (image.channels() != 3) { cvtColor(image, image, COLOR_GRAY2BGR); // 灰度图转BGR } ``` #### 调试技巧(引用[5]) ```cpp Mat roi = image(Rect(0,0,5,5)); // 取左上角5x5区域 cout << "像素示例:\n" << format(roi, Formatter::FMT_PYTHON); ``` 输出格式示例: ``` [[[255, 100, 0], [255, 100, 0], ...], ...] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值