OpenCV用户指南——操作图像

本文介绍了使用OpenCV库进行图像处理的基本操作,包括图像的读取、保存、像素操作及矩阵处理等内容,并演示了如何显示图像。

输入/输出

图像

从文件中读入一副图像:
Mat img = imread(filename)
如果你读入一个jpg文件,缺省情况下将创建一个3通道图像。如果你需要灰度(单通道)图像,使用如下语句:
Mat img = imread(filename, 0);
将图像保存到一个文件:
Mat img = imwrite(filename);

基本图像操作

获取像素的亮度值

要获取像素的亮度值,你必须知道图像的类型和通道的数目。如下例子展示了获取单通道灰度图(类型 8UC1)的(x, y)位置处的像素值:
Scalar intensity = img.at<uchar>(x, y);
intensity.val[0]  中保存从0到255的值。现在我们看一下3通道图像如何获取像素值,颜色顺序为  BGR  (  imread  返回的缺省顺序):
Vec3b intensity = img.at<Vec3b>(x, y);
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];
你可以使用同样的方法处理浮点图像(例如通对一个3通道图像进行Sobel运算得到的浮点图像):
Vec3f intensity = img.at<Vec3f>(x, y);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];
同样的方法也可用于像素值的修改:
img.at<uchar>(x, y) = 128;

一些OpenCV函数,例如calib3d模块中的 projectPoints 函数,需要以 Mat 的格式输入二维或者三维的点。这样的矩阵必须有且仅有一列,这样每行对应一个点,矩阵类型需要是32FC2或者32FC3。这样的矩阵可以很容易的从 std::vector 转换而来:

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

您也可以通过 Mat::at 方法来读写矩阵中的一个元素:

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

内存管理和参考计数(reference counting)

Mat内存储了矩阵/图像的属性(行数,列数,数据类型等)以及一个指向数据的指针。因此几个 Mat 实例可以指向同一个数据。 Mat 中还记录了参考计数(reference count),这样在 Mat 被释放时就知道是否需要释放数据。这儿是一个不需复制数据就创建两个矩阵的例子:

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

这样我们得到了一个3列的32FC1矩阵,而不是1列的32FC3矩阵。 pointsMat 使用 points 的数据,且当它释放时不会是否数据。在这个例子中,开发者需要知道 points 的生命比 pointsMat 长。如果我们需要复制数据,那么请使用 Mat::copyTo 或 Mat::clone :

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

在C API中,开发者必须实现创建输出图像然后再调用函数。与之相比不同的是C++ API支持空的 Mat 类型的输出参数。C++ API会调用 Mat::create 创建结果矩阵。如果矩阵是空的,那将会申请数据空间;如果非空,且大小和类型符合要求,则该函数不做任何事情;如果大小或类型不符合要求,原来的数据会被释放,然后申请新的数据空间。例如:

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

底层操作

为矩阵定义了一系列方便的操作符。我们可以将一个已经存在的灰度图像 img 变成全黑色:

img = Scalar(0);

选择感兴趣区域:

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

将 Mat 转为 C API 数据类型:

Mat img = imread("image.jpg");
IplImage img1 = img;
CvMat m = img;

注意此处无数据复制操作。

将彩色图像转为灰度图像:

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

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

src.convertTo(dst, CV_32F);

显示图像

在算法开发过程中,查看算法的中间结果是非常有用的。OpenCV提供了方便查看图像的方法。类型为 8U 的图像可以使用如下方法显示:

Mat img = imread("image.jpg");

namedWindow("image", CV_WINDOW_AUTOSIZE);
imshow("image", img);
waitKey();

调用 waitKey() 会进入一个消息循环,来等待 image 窗口上的按键动作。 类型为 32F 的图像需要转为 8U 类型。如下:

Mat img = imread("image.jpg");
Mat grey;
cvtColor(img, grey, CV_BGR2GREY);

Mat sobelx;
Sobel(grey, 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);

namedWindow("image", CV_WINDOW_AUTOSIZE);
imshow("image", draw);
waitKey();


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值