OpenCV使用for循环访问Mat数据实现卷积时内核访问异常问题
问题根因
错误核心是cv::Mat的data指针默认类型为uchar*,和你创建的内核类型不匹配:
- 你定义的内核是
CV_32FC1类型,每个元素是32位浮点数,直接通过krn.data[下标]访问只会读取到对应内存地址的单字节无符号整数值,完全不是你预期的1/9≈0.11的浮点数值,因此计算结果全部混乱。 - 额外的小问题:你把
sum定义为int类型,浮点计算的小数部分会被直接截断,也会引入计算误差。
解决方案
既然无法使用at<float>接口访问内核,可以手动将krn.data强制转换为float*类型后再按索引读取,同时调整sum的类型保证精度,修复后的代码如下:
for (int r = 0; r < image.rows - krn.rows; ++r) { for (int c = 0; c < image.cols - krn.cols; ++c) { // sum改用float类型存储中间计算结果,避免小数截断 float sum = 0.f; // 先把内核的data指针强转为float*,匹配CV_32FC1的元素类型 const float* krn_ptr = (const float*)krn.data; for (int rs = 0; rs < krn.rows; ++rs) { for (int cs = 0; cs < krn.cols; ++cs) { // 读取float类型的内核值,乘以图像的uint8像素值 sum += krn_ptr[rs * krn.cols + cs] * image.data[(r + rs) * image.cols + c + cs]; } } // 计算完成后转成uint8存入输出图像,加0.5做四舍五入减少误差 output.data[(r+1)*src.cols + c + 1] = (uchar)(sum + 0.5f); } }
注意事项
如果你的内核内存不是连续存储(比如做过ROI裁剪等操作),不要直接用rs*krn.cols+cs计算索引,需要结合krn.step做偏移计算,通用的访问写法如下:
float val = *(const float*)(krn.data + rs * krn.step + cs * sizeof(float));
内容的提问来源于stack exchange,提问作者l000000l
相关产品推荐
相关产品推荐

