Java 如何有效地找到单个像素的标准偏差';时间的价值是什么?(来自视频源)
(请注意,我的应用程序在1920x1080@60fps,并在录制后进行处理和计算。录制的视频均小于~6秒。) 我目前正在开发一种在android设备上运行的图像处理算法,需要计算单个像素值随时间的标准偏差(和平均值)。换句话说,我希望能够确定坐标(x,y)处任意像素在z秒/帧上的标准偏差。 我使用VideoCapture逐帧读取视频提要 OpenCV似乎没有提供跨时间轴处理的函数,因此我不得不实现自己的处理函数。目前,我的算法使用增量计算方法(此处有更多介绍:)来计算stdev,但在移动设备上运行非常缓慢。我使用这种迭代方法是因为我最初尝试将每个像素的数据组织到单独的向量/列表中,然后对其执行平均值和stdev计算,但考虑到视频分辨率、帧速率和视频持续时间,我的内存不足Java 如何有效地找到单个像素的标准偏差';时间的价值是什么?(来自视频源),java,android,opencv,image-processing,Java,Android,Opencv,Image Processing,(请注意,我的应用程序在1920x1080@60fps,并在录制后进行处理和计算。录制的视频均小于~6秒。) 我目前正在开发一种在android设备上运行的图像处理算法,需要计算单个像素值随时间的标准偏差(和平均值)。换句话说,我希望能够确定坐标(x,y)处任意像素在z秒/帧上的标准偏差。 我使用VideoCapture逐帧读取视频提要 OpenCV似乎没有提供跨时间轴处理的函数,因此我不得不实现自己的处理函数。目前,我的算法使用增量计算方法(此处有更多介绍:)来计算stdev,但在移动设备上运
// Define window boundaries
int startFrame = i * frameRate + temporalSizeRBF;
int endFrame = (i + 1) * frameRate + temporalSizeRBF - 1;
// Calculating Mean and STD for current window
// First frame (frame 0)
vc.read(frame);
// Extract only red channel
Core.extractChannel(frame, redMat, 2);
redMat.convertTo(mean, CvType.CV_64FC1, 1/255.0);
stdev = Mat.zeros(frameHeight, frameWidth, CvType.CV_64FC1);
// Rest of the frames [1:frameRate)
for (int j = startFrame + 1; j <= endFrame; j++) {
double n = j - startFrame + 1;
Log.d(TAG, "Current Frame: " + n);
vc.read(frame);
Core.extractChannel(frame, redMat, 2);
redMat.convertTo(convRedMat, CvType.CV_64FC1, 1/255.0);
// Per row
for (int x = 0; x < frame.rows(); x++) {
// Per col
for (int y = 0; y < frame.cols(); y++) {
double newStd = (stdev.get(x, y)[0] * ((n - 2) / (n - 1))) + ((1 / n) * Math.pow(convRedMat.get(x, y)[0] - mean.get(x, y)[0], 2));
double newMean = (convRedMat.get(x, y)[0] + (n - 1) * mean.get(x, y)[0]) / n;
stdev.put(x, y, newStd);
mean.put(x, y, newMean);
}
}
}
//定义窗口边界
int startFrame=i*帧速率+临时IZERBF;
int endFrame=(i+1)*帧速率+TIMALSIZERBF-1;
//计算当前窗口的平均值和标准差
//第一帧(第0帧)
vc.read(frame);
//只提取红色通道
核心。提取通道(框架,红垫,2);
redMat.convertTo(平均值,CvType.CV_64FC1,1/255.0);
stdev=Mat.zero(帧高、帧宽、CvType.CV_64FC1);
//其余帧[1:帧速率)
对于(int j=startFrame+1;j由于OpenCV Java上缺少合适的3+维矩阵(至少对于OCV 3.4),我决定继续并改进计算Stdev的迭代方法。我使用OpenCV在其核心库()中提供的数组操作,而不是逐像素遍历
这是我的解决办法
int startFrame = i * fps + offset;
int endFrame = (i + 1) * fps + offset - 1;
// Calculating STD for current window
// First frame (frame 0)
frame = frames.get(startFrame);
Imgproc.cvtColor(frame, bgr, Imgproc.COLOR_YUV2BGR_I420);
// Extract only red channel
Core.extractChannel(bgr, redMat, 2);
redMat.convertTo(mean, CvType.CV_32FC1, 1/255.0);
var = Mat.zeros((int) frameSize.height, (int) frameSize.width, CvType.CV_32FC1);
// Rest of the frames [1:frameRate)
for (int j = startFrame + 1; j <= endFrame; j++) {
double n = j - startFrame + 1;
Log.d(TAG, "Current Frame: " + n);
frame = frames.get(j);
Imgproc.cvtColor(frame, bgr, Imgproc.COLOR_YUV2BGR_I420);
Core.extractChannel(bgr, redMat, 2);
redMat.convertTo(convRedMat, CvType.CV_32FC1, 1/255.0);
// Calculate the iterative variance and mean for this frame
// Var(n) = (n-2)/(n-1)*var(n-1) + 1/n*(X(n) - Mean(n-1))^2
Core.multiply(var, new Scalar((n-2)/(n-1)), var); // (n-2)/(n-1)*var(n-1)
Core.subtract(convRedMat, mean, temp1); // (X(n) - Mean(n-1))
Core.multiply(temp1, temp1, temp2); // (X(n) - Mean(n-1))^2
Core.multiply(temp2, new Scalar(1/n), temp2); // 1/n*(X(n) - Mean(n-1))^2
Core.add(var, temp2, var); // (n-2)/(n-1)*var(n-1) + 1/n*(X(n) - Mean(n-1))^2
// Mean(n) = 1/n*(X(n) + (n-1)*Mean(n-1))
Core.multiply(mean, new Scalar(n-1), temp1); // (n-1)*Mean(n-1)
Core.add(convRedMat, temp1, temp2); // X(n) - (n-1)*Mean(n-1)
Core.multiply(temp2, new Scalar(1/n), mean);
}
int startFrame=i*fps+偏移量;
内部帧=(i+1)*fps+offset-1;
//计算当前窗口的STD
//第一帧(第0帧)
frame=frames.get(startFrame);
Imgproc.cvtColor(框架、背景、Imgproc.COLOR_YUV2BGR_I420);
//只提取红色通道
Core.extractChannel(bgr,redMat,2);
redMat.convertTo(平均值,CvType.CV_32FC1,1/255.0);
var=Mat.zero((int)frameSize.height,(int)frameSize.width,CvType.CV_32FC1);
//其余帧[1:帧速率)
对于(int j=startFrame+1;j您的代码似乎提取并处理了整个红色通道,但您的描述说您只需要单个像素的标准偏差?@MarkSetchell My bad,这不清楚。我的意思是,我要计算每个像素在不同时间的标准偏差,用于红色通道中的所有像素。注意在.get(x,y)
上的速度非常慢。要处理每个像素,您应该使用cv::Mat
提供的迭代器,或者使用原始指针。