1.构造Mat:
#include <stdio.h>
#include<sstream>
#include <string>
#include <iostream>
#include <cstdlib>
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main() {
//1.使用Mat类的create成员函数创建Mat
cv::Mat M0;
M0.create(4, 4, CV_8UC3);//M矩阵的元素默认初始化为205;
cout << "m0=" << M0 << endl;
//2.使用Mat构造函数初始化,可以不指定初始值
cv::Mat M1(cv::Size(5, 5), CV_8UC1); // 单通道 a矩阵的元素默认初始化为205;
cv::Mat M2 = cv::Mat(cv::Size(5, 5), CV_8UC3); //3通道每个矩阵元素包含3个uchar值
cout << "m1 = " << endl << M1 << endl << endl;
cout << "m2 = " << endl << M2 << endl << endl;
//3.使用Mat构造函数初始化M时指定初始值
Mat M3 = cv::Mat(3, 3, CV_8UC3, Scalar(5, 100, 200));
cout << "m3 = " << endl << M3 << endl << endl;
//4.Matlab式初始化方式
Mat M4 = cv::Mat::zeros(Size(5, 5), CV_8UC1);
Mat M5= cv::Mat::ones(Size(5, 5), CV_8UC1);
Mat M6= cv::Mat::eye(Size(5, 5), CV_64FC1);
cout << "m3 = " << endl << M4 << endl << endl;
cout << "m4 = " << endl << M5 << endl << endl;
cout << "m5 = " << endl << M6 << endl << endl;
//5.随意给M矩阵赋值
Mat M7 = (Mat_<double>(3, 3) << 1, 2, 3, 7, 8, 9, 4, 5, 6);
cout << "m7 = " << endl << M7 << endl << endl;
Mat Rowclone = M7.row(1).clone();
cout << "Rowclone = " << endl << Rowclone << endl;
//6.使用随机数构造任意矩阵
Mat r = Mat(10, 3, CV_8UC3);
randu(r, Scalar::all(0), Scalar::all(255));
cout <<"r="<< r << endl << endl;
system("pause");
return 0;
}
2.访问图像中的元素案例-图像反色:
#include <stdio.h>
#include<sstream>
#include <string>
#include <iostream>
#include <cstdlib>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
//Vec的表示----Vec2b,Vec3b,Vec2s, Vec3s
//(1)Vec2b—表示每个Vec2b对象中, 存储2个char(字符型)数据
//typedef Vec<uchar, 2> Vec2b; 、
//(2)Vec3b—表示每一个Vec3b对象中, 存储3个char(字符型)数据, 比如用这样的对象, 去存储RGB图像中的一个像素点
//typedef Vec<uchar, 3> Vec3b;
//(3)Vec4b—表示每一个Vec4b对象中, 存储4个字符型数据, 用这样的类对象去存储—4通道RGB + Alpha的图像中的像素点
//typedef Vec<uchar, 4> Vec4b;
//(4)Vec2s—表示这个类的每一个类对象,存储2个short int(短整型)的数据
//typedef Vec<short, 2> Vec2s;
//typedef Vec<short, 3> Vec3s;
//typedef Vec<short, 4> Vec4s;
//
//Vec的表示—Vec3b Vec3f
//8U 类型的 RGB 彩色图像可以使用Vec3b
//3 通道 float 类型的矩阵可以使用Vec3f
//对于 Vec 对象,可以使用[] 符号如操作数组般读写其元素,
//
//Vec3b color; //用 color 变量描述一种 RGB 颜色
//color[0] = 255; //0通道的B 分量
//color[1] = 0; //1通道的G 分量
//color[2] = 0; //2通道的R 分量
//1.使用M.at(i,j)访问图像中的像素
void InverseColor1(Mat src, Mat dst) {
int dims = src.channels();
for (int row = 0; row < src.rows; row++) {
for (int col = 0; col < src.cols; col++) {
if (dims == 1)
{
/* saturate_cast<uchar>主要是为了防止颜色溢出操作
原理大致如下
if (data < 0)
data = 0;
elseif(data > 255)
data = 255;*/
dst.at<uchar>(row, col) = saturate_cast<uchar>(255 - src.at<uchar>(row, col));
}
if (dims == 3) {
dst.at<cv::Vec3b>(row, col)[0] = 255 - src.at<cv::Vec3b>(row, col)[0];//0、1、2分别表示B、G、R
dst.at<cv::Vec3b>(row, col)[1] = 255 - src.at<cv::Vec3b>(row, col)[1];
dst.at<cv::Vec3b>(row, col)[2] = 255 - src.at<cv::Vec3b>(row, col)[2];
}
}
}
}
//2.0使用指针ptr<>(row)访问图像中的像素
void InverseColor2(Mat src) {
int rows = src.rows;
int cols = src.cols;
int nSteps = src.cols * src.channels();
for (int i = 0; i < rows; i++) {
uchar* pStarsrc = src.ptr<uchar>(i);
for (int j = 0; j < nSteps;j++) {
pStarsrc[j] = saturate_cast<uchar>(255 - pStarsrc[j]);
}
}
}
//2.1 使用指针ptr<>(row)访问图像中的像素另一种写法
void InverseColor2_1(Mat src) {
int height = src.rows;
int width = src.cols;
int dims = src.channels();
for (int row = 0; row < height; ++row)
{
if (dims == 1) {
uchar* current_row = src.ptr<uchar>(row);
for (int col = 0; col < width; ++col)
{
*current_row++ = 255 - *current_row;//current_row[]数组的首地址,每行第一个像素
}
}
if (dims == 3)
{
Vec3b *current_row = src.ptr<Vec3b>(row);
for (int col = 0; col < width; ++col)
{
(*current_row)[0]= 255 - (*current_row)[0];
(*current_row)[1] = 255 - (*current_row)[1];
(*current_row)[2]= 255 - (*current_row)[2];
*current_row++;
}
}
}
}
//2.2使用指针ptr<>(row)反转图像中的像素
void InverseColor2_2(Mat src) {
int dims = src.channels();
for (int row = 0; row < src.rows; row++)
{
for (int col = 0; col < src.cols; col++)
{
if (dims == 1) {
uchar* pData = src.ptr<uchar>(row, col);
*pData = 255 - *pData;
}
if (dims == 3) {
Vec3b* pData = src.ptr<Vec3b>(row, col);//彩图
(*pData)[0] = 255 - (*pData)[0];
(*pData)[1] = 255 - (*pData)[1];
(*pData)[2] = 255 - (*pData)[2];
}
}
}
}
//3.使用MatIterator迭代器
void InverseColor3(Mat src, Mat dst) {
if (src.channels() == 1) {
MatIterator_<uchar>srcbeg, srcend, dstbeg, dstend;
srcbeg = src.begin<uchar>();
srcend = src.end<uchar>();
dstbeg = dst.begin<uchar>();
dstend = dst.end<uchar>();
while (srcbeg != srcend) {
(*dstbeg) = 255 - (*srcbeg);
srcbeg++;
dstbeg++;
}
}
if(src.channels()==3){
MatIterator_<Vec3b>srcbeg, srcend, dstbeg, dstend;
srcbeg = src.begin<Vec3b>();
srcend = src.end<Vec3b>();
dstbeg = dst.begin<Vec3b>();
dstend = dst.end<Vec3b>();
while(srcbeg!=srcend) {
(*dstbeg)[0] = 255-(*srcbeg)[0];
(*dstbeg)[1] = 255 - (*srcbeg)[1];
(*dstbeg)[2] = 255 - (*srcbeg)[2];
srcbeg++;
dstbeg++;
}
}
}
//4.利用LUT查表法,opencv中LUT函数如下:
//void LUT(InputArray src, InputArray lut, OutputArray dst);
//src表示的是输入图像(可以是单通道也可是3通道)
//lut表示查找表(查找表也可以是单通道,也可以是3通道,如果输入图像为单通道,那查找表必须为单通道,若输入图像为3通道,
// 查找表可以为单通道,也可以为3通道,若为单通道则表示对图像3个通道都应用这个表,若为3通道则分别应用 )
//dst表示输出图像
void InverseColor4(Mat src, Mat dst) {
if (src.channels() == 1) {
uchar LutTable[256];
for (int i = 0; i < 256; ++i)
{
LutTable[i] = 255 - i;
}
Mat lookUpTable(1, 256, CV_8UC1, LutTable);
//uchar* pData = lookUpTable.data;
建立映射表
//for (int i = 0; i < 256; ++i)
//{
// pData[i] = LutTable[i];
//}
// 应用索引表进行查找
cv:: LUT(src, lookUpTable, dst);
}
if (src.channels() == 3) {
// 建立LUT 反色table
uchar LutTable[256 * 3];
for (int i = 0; i < 256; ++i)
{
LutTable[i * 3] = 255 - i;
LutTable[i * 3 + 1] = 255 - i;
LutTable[i * 3 + 2] = 255 - i;
}
Mat lookUpTable(1, 256, CV_8UC3, LutTable);
// 应用索引表进行查找
cv:: LUT(src, lookUpTable, dst);
}
}
//5.使用data结合step访问图像像素,成员函数step是返回该Mat对象一行所占的数据字节数。
//成员函数data:uchar类型的指针,指向Mat数据矩阵的首地址
void InverseColor5(Mat src) {//该函数有问题
uchar* pData = src.data;
MatStep mst = src.step;
for (int row = 0; row < src.rows; row++)
{
for (int col = 0; col < src.cols; col++)
{
*(pData + row * mst + col * src.channels() + 0) = 255 - *(pData + row * mst + col * src.channels() + 0);
*(pData + row * mst + col * src.channels() + 1) = 255 - *(pData + row * mst + col * src.channels() + 1);
*(pData + row * mst + col * src.channels() + 2) = 255 - *(pData + row * mst + col * src.channels() + 2);
}
}
}
int main()
{
Mat srcImage, srcImg,srcs;
srcImage = imread("E:\\vs2019wenjian\\Cpptest\\data\\face.png"); //原图
cvtColor(srcImage, srcImg, COLOR_BGR2GRAY); //转化为灰度图
cv::imwrite("E:\\vs2019wenjian\\Cpptest\\data\\test04.jpg", srcImg);
if (srcImage.empty())
{
cout << "can not load image" << endl;
return -1;
}
// InverseColor2(srcImage);
/* InverseColor2_1(srcImage);
InverseColor2_1(srcImg);*/
InverseColor1(srcImage,srcImage);
InverseColor1(srcImg,srcImg);
/* uchar lutData[256];
for (int i = 0; i < 256; i++)
{
if (i <= 100)
lutData[i] = 0;
if (i > 100 && i <= 200)
lutData[i] = 100;
if (i > 200)
lutData[i] = 255;
}
Mat lut(1, 256, CV_8UC1, lutData);
LUT(srcImg, lut, b);*/
cv::imwrite("E:\\vs2019wenjian\\Cpptest\\data\\test02.jpg",srcImage);
cv::imwrite("E:\\vs2019wenjian\\Cpptest\\data\\test03.jpg", srcImg);
std:: system("pause");
return 0;
}
图像反色的结果如图: