学 OpenCV 时总会撞见两套图像结构:老的 IplImage 和新的 cv::Mat。2015 年前后教材还在大量用 IplImage;今天结论已经很明确:新代码用 Mat。
简史
IplImage来自 Intel Image Processing Library 风格,是 C-API 核心类型。需要cvCreateImage/cvReleaseImage手动管理。cv::Mat是 C++ API 的矩阵/图像类,引用计数 自动释放,支持 ROI、类型系统、与现代 STL 风格算法更好集成。
对比
| 维度 | IplImage | Mat |
|---|---|---|
| 语言风格 | C | C++ |
| 内存 | 手动 | 自动(引用计数) |
| 新功能 | 基本冻结 | 持续更新 |
| 示例代码 | 老书/老博客 | 官方新文档 |
| 安全性 | 易泄漏/悬挂 | 仍可能误用,但轻松很多 |
转换
IplImage* ipl = ...;
cv::Mat m = cv::cvarrToMat(ipl); // 共享数据,注意生命周期
// 深拷贝:
cv::Mat m2 = cv::cvarrToMat(ipl).clone();
反过来(仅维护老接口时):
IplImage ipl = cvIplImage(mat); // 视 OpenCV 版本 API 略有差异
注意:共享数据时,不要先 release 源再用目标。
迁移建议
- 新项目直接
Mat+VideoCapture+imshow - 维护老项目时,在边界
cvarrToMat,内部别继续扩散 IplImage - OpenCvSharp 用户使用与
Mat对应的类型,避免IplImage封装
小结
「有的方法只有 IplImage 才有」在早期部分成立,现在几乎不成立。把 IplImage 当作历史兼容层即可;默认 Mat。
现代代码骨架
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
Mat img = imread("a.jpg");
if (img.empty()) return 1;
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
imshow("g", gray);
waitKey(0);
return 0;
}
全程无需 IplImage。若链接老插件返回 IplImage*,在边界 cvarrToMat 一次,内部仍用 Mat。
OpenCV 4 文档与示例均以 Mat 为准;继续学 IplImage 性价比低。