从文件加载图像:
Mat imread( const String& filename, int flags = IMREAD_COLOR )
filename:文件名
flags:读取图片的颜色类型
支持图片格式:
1、windows位图:*.bmp,*.dib
2、JPEG文件:*.jpg,*.jpe,*.jpeg
3、JPEG 2000 文件
4、PNG 图片:*.png
5、便携文件格式
6、Sun rasters
7、TIFF文件
flags参数:
CV_LOAD_IMAGE_ANYDEPTH 返回图像的深度不变
CV_LOAD_IMAGE_COLOR 总是返回一个彩色图
CV_LOAD_IMAGE_GRAYSCALE 总是返回一个灰度图
flag =-1,8位深度,原通道
flag = 0,8位深度,1通道
flag = 1, 8位深度,3通道
flag = 2,原深度 ,1通道
flag = 3, 原深度 ,3通道
flag = 4,8位深度,3通道
imwrite(filename,img)
注意:
文件的格式由其扩展名决定。
使用imdecode和imencode从/到内存而不是文件读写图像。
Mat img = imread(“image.jpg”);
namedWindow(“image”,WINDOW_AUTOSIZE);
imshow(“image”,img);
完整代码如下:
#include
#include
int readAndWriteDemo()
{
//读入图片
std::string imagename = "Standard_image/lena.jpg";
cv::Mat img = cv::imread(imagename);
//如果读入图像失败
if (img.empty())
{
std::cout << "miss the image file : " + imagename << std::endl;
return - 1;
}
cv::imwrite("savelena.jpg", imagename);
//创建窗口
cv::namedWindow("image", 1);
//显示图像
cv::imshow("image", img);
//等待按键,按键盘任意键返回
cv::waitKey(0);
return 0;
}
为了获得像素强度值,您必须知道图像的类型和通道数。以下是单通道灰度图像(类型8UC1)和像素坐标x和y的示例:
Scalar intensity = img.at(y, x);
函数 at()来实现读去矩阵中的某个像素,或者对某个像素进行赋值操作。下面两行代码演示了 at()函数的使用方法。
uchar value = grayim.at
(i,j);//读出第 i 行第 j 列像素值
grayim.at(i,j)=128; //将第 i 行第 j 列像素值设置为 128
要对图像进行遍历例程代码
#include
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int usingAtDemo(int argc, char* argv[])
{
Mat grayimg(600, 800, CV_8UC1); //单通道
Mat colorimg(600, 800, CV_8UC3); //三通道
//遍历所有像素,并设置像素值
for( int i = 0; i < grayimg.rows; ++i)
for( int j = 0; j < grayimg.cols; ++j )
grayimg.at<uchar>(i,j) = (i+j)%255;
//遍历所有像素,并设置像素值
for( int i = 0; i < colorimg.rows; ++i)
for( int j = 0; j < colorimg.cols; ++j )
{
Vec3b px;
px[0] = i%255; //Blue
px[1] = j%255; //Green
px[2] = 0; //Red
colorimg.at<Vec3b>(i,j) = px;
}
//显示结果
imshow("grayimg", grayimg);
imshow("colorimg", colorimg);
waitKey(0);
return 0;
}
迭代器可以方便地遍历所有元素。Mat 也增加了迭代器的支持,以便于矩阵元素的遍历。
#include
#include
int usingSTLDemo(int argc, char* argv[])
{
//创建 mat 类
//CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
cv::Mat grayimg(600, 800, CV_8UC1, cv::Scalar(0)); //创建行数为 600,列数为 800,通道数为 1 的图像, Scalar并初始化位0
cv::Mat colorimg(600, 800, CV_8UC3);
//遍历所有像素,并设置像素值 MatIterator_ 是一个迭代器
cv::MatIterator_<uchar> grayit, grayend;
for (grayit = grayimg.begin<uchar>(), grayend = grayimg.end<uchar>(); grayit != grayend; ++grayit)
{
*grayit = rand() % 255;
}
//遍历所有像素,并设置像素值, MatIterator_ 是一个迭代器
cv::MatIterator_<cv::Vec3b> colorit, colorend;
for (colorit = colorimg.begin<cv::Vec3b>(), colorend = colorimg.end<cv::Vec3b>(); colorit != colorend; ++colorit)
{
*colorit = (255, 255, 255);
}
//显示结果
cv::imshow("grayim", grayimg);
cv::imshow("colorim", colorimg);
cv::waitKey(0);
return 0;
}
定义ROI区域
方法一:使用构造函数
//创建宽度为 320,高度为 240 的 3 通道图像
Mat img(Size(320,240),CV_8UC3);
//roi 是表示 img 中 Rect(10,10,100,100)区域的对象
//Rect四个形参分别是:x坐标,y坐标,长,高;注(x,y)指矩形的左上角点;
Mat roi(img, Rect(10,10,100,100));
方法二:括号运算符
Mat roi = img(Rect(10,10,100,100));
方法三: Range 对象来定义感兴趣区域
//指定感兴趣行或列的范围(Range),Range是指从起始索引到终止索引的一段联系序列
Mat roi = img(Range(250, 250 +xleng), Range(200, 200 + yleng));
//Range两个形参分别是:起始行或列,起始行或列+偏移量
Mat是一种保持矩阵/图像特征(行和列数,数据类型等)和指向数据的指针的结构。所以没有什么可以阻止我们有几个Mat对应于相同数据的实例。当Mat的特定实例被破坏时,Mat保留一个引用计数,指示数据是否必须被释放。以下是创建两个矩阵而不复制数据的示例:
std::vector<Point3f> points;
// .. fill the array
Mat pointsMat = Mat(points).reshape(1);
因此,我们得到一个32FC1矩阵与3列而不是32FC3矩阵与1列。pointsMat使用点数据,销毁时不会释放内存。然而,在这种特殊情况下,开发人员必须确保点的生命周期比pointMat长。如果我们需要复制数据,可以使用例如cv :: Mat :: copyTo或cv :: Mat :: clone:
Mat img = imread(“image.jpg”);
Mat img1 = img.clone();
从颜色到灰度的转换:
Mat img = imread("image.jpg"); // loading a 8UC3 image
Mat grey;
cvtColor(img, grey, COLOR_BGR2GRAY);
将图像类型从8UC1更改为32FC1:
src.convertTo(dst,CV_32F);
#include
#include
int main()
{
//读入图片
std::string imagename = "Standard_image/lena.jpg";
cv::Mat img = cv::imread(imagename), resizeimg, resizeimg2;
//如果读入图像失败
if (img.empty())
{
std::cout << "miss the image file : " + imagename << std::endl;
return -1;
}
cv::resize(img, resizeimg, cv::Size(img.cols / 2.0, img.rows / 2.0));
cv::resize(img, resizeimg2, cv::Size(img.cols * 1.2, img.rows * 1.2));
//显示图像
cv::imshow("原图", img);
cv::imshow("缩小", resizeimg);
cv::imshow("放大", resizeimg2);
//等待按键,按键盘任意键返回
cv::waitKey();
return 0;
}
#include
#include
int rotateDemo()
{
cv::Mat src, dst;
float angle = - 90.0;
src = cv::imread("Standard_image/lena.jpg", cv::IMREAD_COLOR);
//从文件读入图片
cv::Point2f center = cv::Point2f(static_cast<float>(src.cols / 2), static_cast<float>(src.rows / 2));
//定义中心点的坐标,2f的意思为float型,中心点极为X,Y即宽度与高度的二分之一
cv::Mat affineTrans = cv::getRotationMatrix2D(center, angle, 1.0);
//getRotationMatrix2D为图像旋转的函数
//第一个参数center是旋转中心点
//第二个参数angle为旋转角度
//第三个1.0的参数为double scale:图像缩放因子
cv::warpAffine(src, dst, affineTrans, src.size());
//cv::warpAffine(src, dst, affineTrans, src.size(), cv::INTER_CUBIC, cv::BORDER_REPLICATE);
//仿射变换函数warpAffine
//第一个参数src为输入原图像
//第二个参数dst为输出图像
//第三个参数为affineTrans转换矩阵
//第四个参数为输出图像的size大小
//第五个参数为立方差值法
//第六个参数为边界用上下行或者左右列来复制填充
cv::imshow("src", src);
cv::imshow("dst", dst);
//显示图片
cv::waitKey(0);
//等待按键下
return 0;
}
#include
#include
#define NAME "name"
//g(x) = alpha*f(x) + beta
int alpha = 100; //对比度
int beta = 0; //亮度
cv::Mat img;
void ProcessOpt()
{
//创建初始化为0的图片矩阵
cv::Mat new_img = cv::Mat::zeros(img.size(), img.type());
//
img.convertTo(new_img, -1, alpha*0.01, beta);
cv::imshow(NAME, new_img);
}
void onAlphaChange(int, void*)
{
ProcessOpt();
}
void onBetaChange(int, void*)
{
ProcessOpt();
}
int demo()
{
img = cv::imread("Standard_image/lena.jpg", cv::IMREAD_COLOR);
//定义窗口名字
cv::namedWindow(NAME);
//创建滑块
cv::createTrackbar("alpha", NAME, &alpha, 100, onAlphaChange);
cv::createTrackbar("beta", NAME, &beta, 100, onBetaChange);
cv::waitKey(0);
return 0;
}