从文件中读入一副图像:
Mat img = imread(filename)
如果你读入一个jpg文件,缺省情况下将创建一个3通道图像。如果你需要灰度(单通道)图像,使用如下语句:
Mat img = imread(filename, 0);
将图像保存到一个文件:
Mat img = imwrite(filename);
TBD
要获取像素的亮度值,你必须知道图像的类型和通道的数目。如下例子展示了获取单通道灰度图(类型 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);
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();