我如何使用 opencv 取 100 张图像的平均值?
How i can take the average of 100 image using opencv?
我有 100 张图片,每张都是 598 * 598 像素,我想通过取像素的平均值来去除图形和噪声,但是如果我想使用 "pixel by pixel" 的加法,然后除以我将编写一个循环,直到一张图片重复 596*598 次,一百张图片重复 598*598*100 次。
有什么方法可以帮我操作吗?
首先-将图像转换为浮点数。您有 N=100 张图片。想象一下,单个图像是 1 个图像的平均像素值的数组。您需要计算 N 个图像的平均像素值数组。
设 A
- X
图像的平均像素值数组,B
- Y
图像的平均像素值数组。然后 C = (A * X + B * Y) / (X + Y)
- X + Y
图像的平均像素值数组。为了在浮点运算中获得更好的精度,X
和 Y
应该大致相等
您可以在 merge sort 中像子数组一样合并所有图像。在您的情况下,合并操作是 C = (A * X + B * Y) / (X + Y)
,其中 A
和 B
是 X
和 Y
图像
的平均像素值数组
您需要遍历每个图像,并累积结果。由于这很可能会造成溢出,所以可以将每张图片转换为一张CV_64FC3
张图片,并叠加在一张CV_64FC3
张图片上。您也可以为此使用 CV_32FC3
或 CV_32SC3
,即使用 float
或 integer
而不是 double
.
一旦你积累了所有的值,你就可以使用convertTo
到两个:
- 使图像成为
CV_8UC3
- 将每个值除以图像数量,得到实际平均值。
这是创建 100 个随机图像并计算并显示
意思是:
#include <opencv2\opencv.hpp>
using namespace cv;
Mat3b getMean(const vector<Mat3b>& images)
{
if (images.empty()) return Mat3b();
// Create a 0 initialized image to use as accumulator
Mat m(images[0].rows, images[0].cols, CV_64FC3);
m.setTo(Scalar(0,0,0,0));
// Use a temp image to hold the conversion of each input image to CV_64FC3
// This will be allocated just the first time, since all your images have
// the same size.
Mat temp;
for (int i = 0; i < images.size(); ++i)
{
// Convert the input images to CV_64FC3 ...
images[i].convertTo(temp, CV_64FC3);
// ... so you can accumulate
m += temp;
}
// Convert back to CV_8UC3 type, applying the division to get the actual mean
m.convertTo(m, CV_8U, 1. / images.size());
return m;
}
int main()
{
// Create a vector of 100 random images
vector<Mat3b> images;
for (int i = 0; i < 100; ++i)
{
Mat3b img(598, 598);
randu(img, Scalar(0), Scalar(256));
images.push_back(img);
}
// Compute the mean
Mat3b meanImage = getMean(images);
// Show result
imshow("Mean image", meanImage);
waitKey();
return 0;
}
假设图像不需要进行变换(伽玛、颜色 space 或对齐)。 numpy 包可让您快速简洁地完成此操作。
# List of images, all must be the same size and data type.
images=[img0, img1, ...]
avg_img = np.mean(images, axis=0)
这将自动提升元素浮动。如果你想要 BGR888,那么:
avg_img = avg_img.astype(np.uint8)
也可以为每通道 16 位执行 uint16。如果每个通道处理 8 位,几乎肯定不需要 100 张图像。
我有 100 张图片,每张都是 598 * 598 像素,我想通过取像素的平均值来去除图形和噪声,但是如果我想使用 "pixel by pixel" 的加法,然后除以我将编写一个循环,直到一张图片重复 596*598 次,一百张图片重复 598*598*100 次。
有什么方法可以帮我操作吗?
首先-将图像转换为浮点数。您有 N=100 张图片。想象一下,单个图像是 1 个图像的平均像素值的数组。您需要计算 N 个图像的平均像素值数组。
设 A
- X
图像的平均像素值数组,B
- Y
图像的平均像素值数组。然后 C = (A * X + B * Y) / (X + Y)
- X + Y
图像的平均像素值数组。为了在浮点运算中获得更好的精度,X
和 Y
应该大致相等
您可以在 merge sort 中像子数组一样合并所有图像。在您的情况下,合并操作是 C = (A * X + B * Y) / (X + Y)
,其中 A
和 B
是 X
和 Y
图像
您需要遍历每个图像,并累积结果。由于这很可能会造成溢出,所以可以将每张图片转换为一张CV_64FC3
张图片,并叠加在一张CV_64FC3
张图片上。您也可以为此使用 CV_32FC3
或 CV_32SC3
,即使用 float
或 integer
而不是 double
.
一旦你积累了所有的值,你就可以使用convertTo
到两个:
- 使图像成为
CV_8UC3
- 将每个值除以图像数量,得到实际平均值。
这是创建 100 个随机图像并计算并显示 意思是:
#include <opencv2\opencv.hpp>
using namespace cv;
Mat3b getMean(const vector<Mat3b>& images)
{
if (images.empty()) return Mat3b();
// Create a 0 initialized image to use as accumulator
Mat m(images[0].rows, images[0].cols, CV_64FC3);
m.setTo(Scalar(0,0,0,0));
// Use a temp image to hold the conversion of each input image to CV_64FC3
// This will be allocated just the first time, since all your images have
// the same size.
Mat temp;
for (int i = 0; i < images.size(); ++i)
{
// Convert the input images to CV_64FC3 ...
images[i].convertTo(temp, CV_64FC3);
// ... so you can accumulate
m += temp;
}
// Convert back to CV_8UC3 type, applying the division to get the actual mean
m.convertTo(m, CV_8U, 1. / images.size());
return m;
}
int main()
{
// Create a vector of 100 random images
vector<Mat3b> images;
for (int i = 0; i < 100; ++i)
{
Mat3b img(598, 598);
randu(img, Scalar(0), Scalar(256));
images.push_back(img);
}
// Compute the mean
Mat3b meanImage = getMean(images);
// Show result
imshow("Mean image", meanImage);
waitKey();
return 0;
}
假设图像不需要进行变换(伽玛、颜色 space 或对齐)。 numpy 包可让您快速简洁地完成此操作。
# List of images, all must be the same size and data type.
images=[img0, img1, ...]
avg_img = np.mean(images, axis=0)
这将自动提升元素浮动。如果你想要 BGR888,那么:
avg_img = avg_img.astype(np.uint8)
也可以为每通道 16 位执行 uint16。如果每个通道处理 8 位,几乎肯定不需要 100 张图像。