减去两个 CV_64FC3 矩阵并保持负值
Posted
技术标签:
【中文标题】减去两个 CV_64FC3 矩阵并保持负值【英文标题】:Subtracting two CV_64FC3 matrices and keeping the negative values 【发布时间】:2021-03-17 21:29:11 【问题描述】:据我所知,减去两个非浮点矩阵会产生预期结果,但减去两个 CV_64FC3(以及 CV_32F)矩阵会将负值裁剪为 0.0 并且将结果归一化在 0.0 和1.0。我知道这些限制并阅读了相关文档,但仍然无法减去两个矩阵。
Mat lowpass1, lowpass2, mask;
mask.convertTo(mask, CV_32F);
lowpass1.convertTo(lowpass1, CV_32F);
lowpass2.convertTo(lowpass2, CV_32F);
// all other variables (high_b1, high_a0 etc.) are double
// and in the range of -1.0 to 1.0 but never 0.0
// frame and prev_frame are CV_32F matrices
lowpass1 = (-high_b1 * lowpass1 + high_a0 * frame + high_a1 * prev_frame) / high_b0;
lowpass2 = (-low_b1 * lowpass2 + low_a0 * frame + low_a1 * prev_frame) / low_b0;
mask = lowpass1 - lowpass2
尽管 lowpass1 和 lowpass2 包含非零正值,但减法始终为 0。我假设它正在裁剪和/或四舍五入到最接近的整数。
mask = lowpass2 - lowpass1
这也给出了与上述完全相同的结果。
工作的最小示例;
#include <iostream>
#include <vector>
#include <list>
#include <opencv2/opencv.hpp>
using std::cout;
using std::string;
using std::list;
using std::vector;
using cv::Mat;
int main()
cv::VideoCapture cap("small.mp4");
const int level = 2;
vector<Mat> *data = new vector<Mat>;
vector<vector<Mat>> pyramid;
pyramid.resize(level);
Mat frame;
while (true)
cap >> frame;
if (frame.empty())
break;
frame.convertTo(frame, CV_32F, 1.0 / 255.0f);
data->push_back(frame.clone());
Mat current = frame.clone();
for (int i = 0; i < level; i++)
Mat down, up;
if (i == (level - 1))
pyramid[i].push_back(current);
break;
cv::pyrDown(current, down);
cv::pyrUp(down, up, current.size());
pyramid[i].push_back(current - up);
current = down;
double low_a0 = 0.04979798;
double low_a1 = 0.04979798;
double low_b0 = 1;
double low_b1 = -0.90040404;
double high_a0 = 0.13672874;
double high_a1 = 0.13672874;
double high_b0 = 1;
double high_b1 = -0.72654253;
vector<vector<Mat>> filtered;
filtered.resize(level);
for (int i = 1; i < pyramid.size(); i++)
Mat lowpass1 = pyramid[i][0], lowpass2 = pyramid[i][0];
for (int j = 1; j < pyramid[i].size(); j++)
lowpass1 = (-high_b1 * lowpass1 + high_a0 * pyramid[i][j] + high_a1 * pyramid[i][j-1]) / high_b0;
lowpass2 = (-low_b1 * lowpass2 + low_a0 * pyramid[i][j] + low_a1 * pyramid[i][j - 1]) / low_b0;
filtered[i].push_back(lowpass1 - lowpass2);
源视频; http://techslides.com/demos/sample-videos/small.mp4
【问题讨论】:
所有高低帧prev_frame变量的类型是什么?如果原始类型或大小不合适,OpenCV 运算符可以轻松地用另一种类型的矩阵覆盖输出变量。作为一个快速的技巧,你可以在计算低通 1 和低通 2 之后做lowpass1.convertTo(lowpass1, CV_32F); lowpass2.convertTo(lowpass2, CV_32F);
问题可能是你实际上并没有转换lowpass1
或lowpass2
——你有lowpass1.convertTo(filtre, CV_32F);
和lowpass2
一样的东西......所以你写了转换后的数组到您在以后的语句中不使用的其他矩阵。
你如何测试掩码的值? imshow
将缩放和裁剪值以进行渲染。 imwrite
也不能很好地工作,因为图像类型通常不知道负值。您可能需要以不同的方式进行测试。如果您想保存和加载 32F 或 64F 矩阵(或任何其他非图像类型),您可以使用将矩阵保存为某种 xml 文件中的字符串的 Serializer 函数(抱歉,不记得名称 atm)。跨度>
@DanMašek,从我的母语翻译时出错,在原始代码中是lowpass1.convertTo(lowpass1, CV_32F);
,很抱歉造成混淆。
@Micka,我同时使用 imshow 并将值输出到 txt 文件。计算后尝试了转换破解,但得到了相同的结果。尽管在 imshow 和 txt 文件中,lowpass1 和 lowpass2 确实有效。
【参考方案1】:
问题出在这部分;
lowpass1 = (-high_b1 * lowpass1 + high_a0 * pyramid[i][j] + high_a1 * pyramid[i][j-1]) / high_b0;
lowpass2 = (-low_b1 * lowpass2 + low_a0 * pyramid[i][j] + low_a1 * pyramid[i][j - 1]) / low_b0;
由于在公式和代码的左侧使用了 lowpass1 和 lowpass2,它搞砸了一些东西,但我不确定它到底做了什么。改成这个后;
Mat lowpass1_, lowpass2_;
lowpass1_ = ( high_b1 * lowpass1 + high_a0 * pyramid[i][j] + high_a1 * pyramid[i][j - 1]);
lowpass2_ = ( low_b1 * lowpass2 + low_a0 * pyramid[i][j] + low_a1 * pyramid[i][j - 1]) ;
计算是正确的,没有归零等。感谢所有回复。
【讨论】:
以上是关于减去两个 CV_64FC3 矩阵并保持负值的主要内容,如果未能解决你的问题,请参考以下文章