Chapter_04 图像操作

一. 输入/输出

① 从一个文件中加载一个图像
Mat img = imread(filename);

如果你想读取一个jpg图像,默认会创建一个3通道的图像.如果你需要一个灰度图像,使用:

Mat img = imread(filename,IMREAD_GRAYSCALE);

注意:

文件的格式由其内容(前几个字节)决定. 将图像保存到文件.

② 写入图像到一个文件中
imwrite(filename,img);

注意:
文件的格式由其扩展名决定.使用cv::imdecodecv::imencode从内存中读取和写入图像,而不是文件.

二. 图像的基本操作

① 访问像素强度值

为了得到像素的强度值,你必须知道图像的类型和通道的数量.下面是一个单通道灰度图像(类型 8UC1)和像素坐标x和y的示例:

Scalar intensity = img.at<uchar>(Point(x,y));

现在让我们考虑一个BGR颜色排序的3通道图像(imread返回的默认格式):

Vec3b intesity = img.at<Vec3b>(y,x);
uchar blue = intesity.val[0];
uchar green = intesity.val[1];
uchar red = intesity.val[2];

你可以对浮点类型的图像使用相同的方法(例如,可以通过3通道图像上运行Soble来获得这样的图像)(仅限C++):

Vec3f intensity = img.at<Vec3f>(y,x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];

同样的方法可以用来改变像素强度:

img.at<uchar>(y,x) = 128;

Opencv中的有一些函数,特别是来自calib3d模块的函数,比如cv::projectPoints,以Mat的形式获取二维或者三维点的数组.矩阵应该恰好包含一列,每一行对应一个点,对应的矩阵类型应该是32FC2或者32FC3.这样的矩阵可以很容易地从std::vector中构造(仅限C++):

vector<Point2f> points;
// ... fill the array
Mat pointsMat = Mat(points);

你可以使用相同的方法访问这个矩阵中的一个点Mat::at(仅限C++):

Point2f point = pointsMat.at<Point2f>(i,0);

三. 内存管理和引用计数

Mat是这样一中结构体,它保存了矩阵/图像特征(行数和列数,数据类型等)和一个指向数据的指针.因此,没有什么可以阻止我们拥有多个对应相同数据的Mat实例.Mat保持了一个引用计数,当特定的Mat实例被销毁的时候,它告诉数据是否必须被释放.下面是一个在不复制数据的情况下创建两个矩阵的示例(仅限C++):

std::vector<Point3f> points;
// .. fill the array
Mat pointsMat = Mat(points).reshape(1);

结果,我们得到一个三列的32FC1矩阵,而不是1列的32FC3矩阵.pointsMat使用来自points的数据,销毁时不会释放内存.但是,在这个特殊的例子中,开发人员必须确保points的声明周期比pointsMat长.我们如果需要复制数据,可以使用cv::Mat::copyTo或者cv::Mat::clone()来完成.

Mat img = imread("image.jgp");
Mat img1 = img.clone();

可以为每个函数提供空的输出Mat.每个市县对目标矩阵调用Mat::create.如果矩阵为空,则此方法为其分配数据.如果它不是空的,并且具有正确的大小和类型,则该方法不执行任何操作.但是,如果大小或者类型与输入参数不同,则释放(或丢失)数据,并分配新数据.例如:

Mat img = imread("image.jgp");
Mat sobelx;
Sobel(img,sobelx,CV_32F,1,0);

四. 原始操作

矩阵上定了许多方便的运算符.例如,下面展示了我们如何从现有的灰度图像img中生成黑色图像

img = Scalar(0);

选择感应区的区域

Rect r(10,10,100,100);
Mat smallImg = img(r);

将图像从彩色图像转换为灰度图像

Mat img = imread("image.jpg"); // loading a 8UC3 image
Mat gray;
cvtColor(img,gray,COLOR_BGR2GRAY);

将图像的数据类型从8UC1转换为32FC1:

src.convertTo(dst,CV_32F);

五. 可视化图像

在开发的过程中查看算法的中间结果是非常有用的.Opencv提供了一种方便的可视化图像的方法.一个8U的图像可以显示使用:

Mat img = imread("image.jpg");
nameWindow("image",WINDOW_AUTOSIZE);
imshow("image",img);
waitKey();

通过调用waitKey()启动一个循环接收消息,等待图像串口的点击键盘.一个32F的图像需要转换为8U的类型,例如:

Mat img = imread("image.jgp");
Mat gray;
cvtColor(img,gray,COLOR_BGR2GRAY);
Mat sobelX;
Sobel(gray,sobelX,CV_32F,1,0);
double minVal,maxVal;
minMaxLoc(sobelX,&minVal,&maxVal);// find minimum and maximum intensities
Mat draw;
sobelx.convertTo(draw,CV_8U,255.0 / (maxVal - minVal),-minVal * 255.0 / (maxVal - minVal));
nameWindow("image" WINDOW_AUTOSIZE);
imshow("image",draw);
waitKey();

注意:
这里的cv::nameWindow不是必要的,因为它后面紧跟着cv::imshow,它可以用于更该窗口属性或者使用cv::createTrackbar时的时候使用.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值