这个问题对于使用纯C更好地理解图像处理是一项挑战。我已经完成了一个简单的程序,使用C编译的GCC读取非二进制PGM文件。现在,当我尝试读取二进制PGM文件时,它正成为一个问题。可以使用IrvanView将 JPG 转换为 PGM 来获取此二进制PGM文件。
注意:请不要回答任何图像处理库(例如:OpenCV)。
我目前的代码是:
#include <stdio.h>
#include <stdlib.h>
#define WIDTH 1024
#define HEIGHT 768
#define READ_IMAGE_NAME "MY_PGM_FILE_NAME.pgm"
void print_histogram_table(int *histog);
main() {
FILE *fp;
int i,j, height= HEIGHT, width=WIDTH;
char line[100];
// Color depth is 255.
unsigned char pixel_value;
fp = fopen(READ_IMAGE_NAME,"r");
// get the first four lines.
fgets (line,100,fp);
fgets (line,100,fp);
fgets (line,100,fp);
fgets (line,100,fp);
// Histogram helper
int histo[65536];
int x;
for ( x =0; x < 65536; x++) {
histo[x] = 0;
}
for(j=0;j<height;j++) {
for(i=0;i<width;i++) {
fread(&pixel_value, sizeof(unsigned char), 1, fp);
// Turn on the code below, if you want to check color on specific row and column.
// printf("row num. %d column num. %d pixel value=%d\n",j,i,pixel_value);
histo[pixel_value]++;
}
}
// Make histogram
print_histogram_table(histo);
fclose(fp);
getch();
}
void print_histogram_table(int *histog)
{
int x;
for (x= 0; x < 255; x++) {
if ( histog[x] != 0)
printf("Color number %d count %d\n", x, histog[x]);
}
}
我已经阅读了一些与我的问题相关的页面[How to read .PGM format file?],但我找不到任何明确而简单的答案。我为我的代码中的任何错误道歉。任何有关我的代码的建议和批评者将不胜感激。
我上面的脚本无法显示正确的颜色直方图,因为如果你理性思考,你可能会得到100以上的像素颜色(不仅低于100)。那么,主要问题是如何解决这个问题?
编辑我
编辑II
答案 0 :(得分:1)
而且......问题是什么?您的代码看起来几乎可以读取二进制PGM(P5?),它只是缺少对每个像素数据行的换行检查(根据维基百科文章,ASCII和二进制格式在每个像素的末尾都有换行符数据行)。
一些意见:
答案 1 :(得分:1)
我上面的脚本无法显示正确的颜色直方图,因为如果你理性思考,你可能会得到100以上的像素颜色(不仅低于100)。所以,主要的问题是如何解决这个问题?
我假设你的意思是:
现在,在链接图像上运行此程序仅显示100以下像素值的非零直方图条目。我知道图像中至少有一个像素值超过100,所以我的代码中有一个错误。任何人都可以帮我弄清楚为什么会这样吗?
我建议你重新说出你的问题,以明确这一点。
代码表面看起来还不错,假设您只希望它能够处理您链接到的图像。但是,有很多小错误可能会加起来。以下是一些建议:
首先,您无法打印整个直方图。考虑将直方图大小传递给打印直方图的函数。此外,即使的大小匹配(均为256),您仍然会有错误。你永远不会打印第256个值。
int histo[65536];
// ...
print_histogram_table(histo);
// ...
void print_histogram_table(int *histog)
{
int x;
for (x= 0; x < 255; x++) {
if ( histog[x] != 0)
printf("Color number %d count %d\n", x, histog[x]);
}
打开二进制文件时需要指定“二进制”I / O.在UNIX上,这通常没有区别,因为它是默认模式。但是,在Windows上(我假设您正在使用Irfan View时运行Windows),您需要明确声明您需要二进制I / O.
这是第一次处理二进制文件时常见的错误。基本上,一旦fread()
调用捕获EOF
字节,它将停止读取文件,您将获得所有后续读取的垃圾值(可能是最后一次读取的副本)真正的字节),这意味着你实际上并没有阅读整个图像。
fp = fopen(READ_IMAGE_NAME,"r");
// change to:
fp = fopen(READ_IMAGE_NAME,"rb");
您的代码无法处理大量内容:
答案 2 :(得分:0)
关于您的计划的一些注意事项:
以下是您的计划的改进版本,上述要点已得到解决。我希望它有所帮助。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
char line[100];
int width, height, maxval;
unsigned char* image;
unsigned int* histo;
int i;
FILE *fd;
fd = fopen(argv[1], "rb");
if (fd == NULL) {
printf("could not open image file\n");
exit(1);
}
// magic number
fgets(line, sizeof(line), fd);
if (strcmp(line, "P5\n") != 0) {
printf("image is not in PGM format!\n");
fclose(fd);
exit(1);
}
// skip comment
fgets(line, sizeof(line), fd);
// read header
if (fscanf(fd, "%d %d %d\n", &width, &height, &maxval) != 3) {
printf("invalid header\n");
fclose(fd);
exit(1);
}
if (maxval > 255) {
printf("sorry, only 8-bit PGMs are supported at this time!\n");
fclose(fd);
exit(1);
}
printf("width: %d\nheight: %d\nmaxval: %d\n", width, height, maxval);
// read image data
image = malloc(width * height);
if (fread(image, sizeof(unsigned char), width * height, fd) != width * height) {
printf("could not read image\n");
fclose(fd);
exit(1);
}
fclose(fd);
// compute histogram
histo = (int*)calloc(maxval+1, sizeof(int));
for (i = 0; i < width * height; i++)
histo[image[i]]++;
// print histogram
for (i = 0; i <= maxval; i++)
printf("Color number %d count %d\n", i, histo[i]);
// release memory
free(image);
free(histo);
}