Java 如何使用OpenCV在不将所有图像保留在内存中的情况下平均N个图像
我创建了一个类,该类尝试从任意数量的图像(逐个传递)创建一个平均图像 这个进程将在它自己的线程中运行,而其他线程读取图像,进行处理,并将输出传递给这个平均对象 不幸的是,每增加一张图像,平均图像就会变得越来越亮。 我怀疑我的平均函数有错误,但我一直找不到 编辑:我遗漏了等式中的“curImg/curCount”部分。通过此校正,图像现在变暗。我的平均成绩不好 编辑2:我看到我被否决了。我能做些什么来改进这个问题吗Java 如何使用OpenCV在不将所有图像保留在内存中的情况下平均N个图像,java,opencv,image-processing,average,Java,Opencv,Image Processing,Average,我创建了一个类,该类尝试从任意数量的图像(逐个传递)创建一个平均图像 这个进程将在它自己的线程中运行,而其他线程读取图像,进行处理,并将输出传递给这个平均对象 不幸的是,每增加一张图像,平均图像就会变得越来越亮。 我怀疑我的平均函数有错误,但我一直找不到 编辑:我遗漏了等式中的“curImg/curCount”部分。通过此校正,图像现在变暗。我的平均成绩不好 编辑2:我看到我被否决了。我能做些什么来改进这个问题吗 class AverageImage { private Vector&l
class AverageImage {
private Vector<Mat> average = new Vector<>();
private int count = 0;
public void add(Mat img) {
count++;
Vector<Mat> splitImg = new Vector<>();
Mat convertedImg = img.clone();
convertedImg.convertTo(convertedImg, CvType.CV_32FC1);
Core.split(img.clone(), splitImg);
if (average.isEmpty()) {
average = splitImg;
} else {
// prevAverage * (prevCount/curCount) + curImg/curCount
for (int i = 0; i < average.size(); i++) {
Core.multiply(average.get(i), new Scalar((count - 1) / ((double) count)), average.get(i));
Mat temp = new Mat();
Core.divide(count, splitImg.get(i), temp);
Core.add(average.get(i), temp, average.get(i));
}
}
}
public Mat getAverage() {
Mat convertedAverage = new Mat();
Core.merge(average, convertedAverage);
convertedAverage.convertTo(convertedAverage.clone(), CvType.CV_8UC3);
return convertedAverage;
}
}
类平均图像{
私有向量平均值=新向量();
私有整数计数=0;
公共无效添加(材料img){
计数++;
向量拆分img=新向量();
Mat convertedImg=img.clone();
convertedImg.convertTo(convertedImg,CvType.CV_32FC1);
split(img.clone(),splitImg);
if(average.isEmpty()){
平均值=splitImg;
}否则{
//prevAverage*(prevCount/curCount)+curImg/curCount
对于(int i=0;i次要注释:convertedImg
在您的代码中根本没有使用。您可以删除它
你对所谓的世界的决定是正确的。然而,真正困扰您的部分是divide
语句:
Core.divide(count, splitImg.get(i), temp);
,当您调用第一个元素为标量的变量时,正在执行的操作是:
dst(I) = saturate(scale / src(I))
scale
用于划分输出。因此,您正在做的是count/splitImg.get(i)
而实际上您应该做的是splitImg.get(i)/count
。考虑到这一点,divide
不支持拍摄图像并除以系数。但是,一种解决方法是使用核心。将与计数的倒数相乘:
Core.multiply(splitImg.get(i), new Scalar(1.0 / count), temp);
您所需要做的就是更改核心。将
语句除以上面的语句,它就应该可以工作了
// prevAverage * (prevCount/curCount) + curImg/curCount
for (int i = 0; i < average.size(); i++) {
Core.multiply(average.get(i), new Scalar((count - 1) / ((double) count)), average.get(i));
Mat temp = new Mat();
// Core.divide(count, splitImg.get(i), temp);
Core.multiply(splitImg.get(i), new Scalar(1.0 / count), temp);
Core.add(average.get(i), temp, average.get(i));
}
最后,为了计算这个方程的第二项,我们做:
Core.multiply(splitImg.get(i), new Scalar(1.0 / count), temp);
对于数值稳定性,可能最好只存储累积和图像,并在需要平均值时将其除以当前N
注意不要溢出
Core.multiply(splitImg.get(i), new Scalar(1.0 / count), temp);