【发布时间】:2020-05-05 16:00:19
【问题描述】:
我想对 .ppm 文件中的图像应用简单的派生/渐变滤镜 [-1, 0, 1]。
.ppm 文件中的原始二进制数据被读入一维数组:
uint8_t* raw_image_data;
size_t n_rows, n_cols, depth;
// Open the file as an input binary file
std::ifstream file;
file.open("test_image.ppm", std::ios::in | std::ios::binary);
if (!file.is_open()) { /* error */ }
std::string temp_line;
// Check that it's a valid P6 file
if (!(std::getline(file, temp_line) && temp_line == "P6")) {}
// Then skip all the comments (lines that begin with a #)
while (std::getline(file, temp_line) && temp_line.at(0) == '#');
// Try read in the info about the number of rows and columns
try {
n_rows = std::stoi(temp_line.substr(0, temp_line.find(' ')));
n_cols = std::stoi(temp_line.substr(temp_line.find(' ')+1,temp_line.size()));
std::getline(file, temp_line);
depth = std::stoi(temp_line);
} catch (const std::invalid_argument & e) { /* stoi has failed */}
// Allocate memory and read in all image data from ppm
raw_image_data = new uint8_t[n_rows*n_cols*3];
file.read((char*)raw_image_data, n_rows*n_cols*3);
file.close();
然后我将数据中的灰度图像读入一个二维数组,称为image_grayscale:
uint8_t** image_grayscale;
image_grayscale = new uint8_t*[n_rows];
for (size_t i = 0; i < n_rows; ++i) {
image_grayscale[i] = new uint8_t[n_cols];
}
// Convert linear array of raw image data to 2d grayscale image
size_t counter = 0;
for (size_t r = 0; r < n_rows; ++r) {
for (size_t c = 0; c < n_cols; ++c) {
image_grayscale[r][c] = 0.21*raw_image_data[counter]
+ 0.72*raw_image_data[counter+1]
+ 0.07*raw_image_data[counter+2];
counter += 3;
}
}
我想将过滤后的图像写入另一个二维数组gradient_magnitude:
uint32_t** gradient_magnitude;
// Allocate memory
gradient_magnitude = new uint32_t*[n_rows];
for (size_t i = 0; i < n_rows; ++i) {
gradient_magnitude[i] = new uint32_t[n_cols];
}
// Filtering operation
int32_t grad_h, grad_v;
for (int r = 1; r < n_rows-1; ++r) {
for (int c = 1; c < n_cols-1; ++c) {
grad_h = image_grayscale[r][c+1] - image_grayscale[r][c-1];
grad_v = image_grayscale[r+1][c] - image_grayscale[r-1][c];
gradient_magnitude[r][c] = std::sqrt(pow(grad_h, 2) + pow(grad_v, 2));
}
}
最后,我将过滤后的图像写入 .ppm 输出。
std::ofstream out;
out.open("output.ppm", std::ios::out | std::ios::binary);
// ppm header
out << "P6\n" << n_rows << " " << n_cols << "\n" << "255\n";
// Write data to file
for (int r = 0; r < n_rows; ++r) {
for (int c = 0; c < n_cols; ++c) {
for (int i = 0; i < 3; ++i) {
out.write((char*) &gradient_magnitude[r][c],1);
}
}
}
out.close();
然而,输出图像是一团糟。
当我在循环中简单地设置grad_v = 0;(即只计算水平梯度)时,输出看起来是正确的:
当我改为设置grad_h = 0;(即只计算垂直梯度)时,输出很奇怪:
图像的一部分似乎被循环移动了,但我不明白为什么。此外,我尝试了许多图像,并且出现了同样的问题。
任何人都可以看到任何问题吗?非常感谢!
【问题讨论】:
-
您可能会加载 RGB 图像吗?每个像素都有三个值,而不是一个。所以下面的相邻像素是 3*width 字节,而不是宽度。您的输出与该差异一致(图像中的三个垂直带)。
-
如果您需要更详细的帮助,请阅读minimal reproducible example,然后阅读edit您的问题。它目前没有足够的信息来写答案。
-
你能给我们你输入图像的表示吗?
-
抱歉没有包含更多代码——我担心添加太多。我用一个最小的例子更新了这个问题。希望没事?谢谢!
-
你知道梯度幅度的范围吗?为什么你使用 32 位整数并且只保存最低有效字节?
标签: c++ image-processing