OpenCV常见的注意事项(持续更新中)

文章讲述了在OpenCV中如何使用FileStorage类保存和读取Mat数据到XML或YML文件,以保留原始数据。此外,还讨论了Mat的copyTo和convertTo函数的使用,包括数据拷贝和类型转换的注意事项,特别是在浮点数转换为整型时的差异。

保存Mat的原始数据

在图像处理的过程中,常常使用imwrite保存处理后的图片,便于查看处理后的效果,但此函数保存的是图像格式的数据,对Mat数据进行压缩处理。在调试过程中,对比数据修改过程,我们可以使用FileStorage类将Mat数据保存到XML/YML文件中。

保存mat矩阵

cv::FileStorage fs("data.xml", cv::FileStorage::WRITE);
fs << "black" << image;
fs.release();

读取文件数据到mat矩阵

cv::FileStorage fs("data.xml", cv::FileStorage::READ);
cv::Mat black_mat;
fs["black"] >> black_mat;
fs.release();

copyToconvertTo成员函数

void copyTo( OutputArray m, InputArray mask ) const;cv::Mat的成员函数。根据函数说明需要注意两点

  • 数据拷贝之前可能触发m.create(this->size(), this->type());,也就是如果有必要目标matrix重新分配内存
  • 如果指定mask参数,如果调用Mat::create重新分配内存,会初始化为0;
  • mask的size与this一致,只拷贝mask元素为非0的位置的数据到m,The mask has to be of type CV_8U and can have 1 or multiple channels
void test()
{
    cv::Mat image = cv::imread("test.jpg")

    cv::Mat imgYCrCb;
    cv::cvtColor(image, imgYCrCb, cv::COLOR_BGR2YCrCb);

    std::vector<cv::Mat> channels;
    cv::split(image, channels);

    cv::Mat fchny = cv::Mat_<float>(channels[0]);

    cv::Mat white_mask;
    cv::threshold(channels[0], white_mask, 240, 255, cv::THRESH_BINARY);
    // 注意这里要进行转换,否则fchny重新分配空间初始化0在拷贝
    cv::Mat_<float>(channels[0]).copyTo(fchny, white_mask);
    fchny.convertTo(channels[0], channels[0].type(), 1, -0.5);

    cv::Mat encodedImgYCrCb;
    cv::merge(channels, encodedImgYCrCb);

    cv::Mat img_handled;
    cv::cvtColor(encodedImgYCrCb, img_handled, cv::COLOR_YCrCb2BGR);

    cv::imshow("imgYCrCb", imgYCrCb);
    cv::imshow("imgHandled" img_handled);
    cv::waitKey(0);
    cv::destroyAllWindows();
}

这里提示一个注意点,在OpenCV中float转换成整形元素是四舍五入的,与cpp中强制转换中损失小数是不一致的,所以在python代码改写成c++ OpenCV代码时建议使用convertTo成员函数进行处理

void test()
{
    float ffdata[] = {3.2, 3.5, 3.6, -3.2, -3.5, -3.6};
    for(auto data: ffdata)
    {
        std::cout << int(data) << " ";
    }
    std::cout << std::endl;

    // cv::Mat fdata = (cv::Mat_<float>(2, 3) <<3.2, 3.5, 3.6, -3.2, -3.5, -3.6);
    cv::Mat fdata(2, 3, CV_32FC1, ffdata);
    cv::Mat idata = cv::Mat_<int8_t>(fdata);

    cout << fdata << endl;
    cout << idata << endl;
}

输出结果如下:

3 3 3 -3 -3 -3
[3.2, 3.5, 3.5999999;
 -3.2, -3.5, -3.5999999]
[  3,   4,   4;
  -3,  -4,  -4]

对应的Python测试代码

import numpy as np

fdata = np.array([[3.2, 3.5, 3.6], [-3.2, -3.5, -3.6]], dtype=np.float32)
idata = np.array(fdata, dtype=np.int8)
print(fdata)
# [[ 3.2  3.5  3.6]
#  [-3.2 -3.5 -3.6]]
print(idata)
# [[ 3  3  3]
#  [-3 -3 -3]]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

callinglove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值