如何用c++和OpenCV进行基本的图像处理? (读取、修改和保存)

cv::imread读取图像需严格匹配路径与格式,不自动补全扩展名,不提示具体错误;相对路径易因工作目录偏差失败;Windows推荐用正斜杠;必须检查img.empty()。

cv::imread 读取图像时路径和格式必须严格匹配

OpenCV 不会自动补全扩展名,也不会提示“文件不存在”以外的细节。常见错误是传入相对路径但工作目录不是预期位置,或图片实际是 .jpeg 却写了 .jpg。Windows 下路径分隔符用正斜杠 / 更稳妥(cv::imread("img/test.png")),反斜杠需双写 \\。返回值为 cv::Mat,务必检查是否为空:

cv::Mat img = cv::imread("input.jpg");
if (img.empty()) {
    std::cerr << "Failed to load image\n";
    return -1;
}
否则后续操作会静默崩溃或产生不可预测结果。

修改像素值前先确认图像通道数和数据类型

cv::Mat.type() 返回编码值,比如 CV_8UC3 表示 8 位无符号、3 通道(BGR);CV_8UC1 是灰度图。直接用 img.at<:vec3b>(y, x) 访问彩色图像素,但若图是灰度的,会越界崩溃。安全做法是先判断:

if (img.channels() == 3) {
    auto& pixel = img.at(y, x);
    pixel[0] = 0;      // B 分量置 0
} else if (img.channels() == 1) {
    img.at(y, x) = 255; // 置白
}
批量操作推荐用 cv::cvtColorcv::threshold 等内置函数,比手写循环快且不易出错。

cv::imwrite 保存失败通常因路径无效或不支持格式

OpenCV 默认只支持常见后缀:`.png`、`.jpg`、`.bmp`、`.tiff`。写成 `.jpeg` 可能失败(应写 `.jpg`)。目标目录必须已存在,它不会自动创建父级路径。保存前建议验证:

st

d::string out_path = "output.png"; bool saved = cv::imwrite(out_path, img); if (!saved) { std::cerr << "Failed to write " << out_path << "\n"; // 常见原因:out_path 含非法字符、磁盘满、无写权限、img 为空 }
另外,JPEG 不支持透明通道,若原图含 alpha(4 通道),保存前得用 cv::cvtColor(img, img, cv::COLOR_BGRA2BGR) 去掉 alpha,否则可能黑屏或报错。

中文路径或含空格路径会导致 imread/imwrite 失败

OpenCV 3.x/4.x 的 C++ 接口不支持 UTF-8 路径(Windows 下尤其明显),空格也可能被截断。解决方法是改用 OpenCV 的 C 接口绕过:

cv::Mat img;
cv::String utf8_path = u8"测试图.jpg"; // C++11 UTF-8 字符串字面量
img = cv::imread(cv::samples::findFileOrKeep(utf8_path).c_str());
更可靠的做法是:把图像复制到纯英文路径下处理,或改用第三方库(如 stb_image)加载后再转为 cv::Mat。这点容易忽略,调试时花半天才发现是路径问题。