使用纯C显示PGM图像(p5)中的直方图像素值,无需任何图像处理库
这个问题很难理解使用纯C进行的图像处理。我用GCC编译的C编写了一个读取非二进制PGM文件的简单程序。现在,当我试图读取二进制PGM文件时,这就成了一个问题。可通过使用将JPG转换为PGM来获取该二进制PGM文件 注意:请不要使用任何图像处理库(例如:OpenCV)进行回答 我目前的代码是:使用纯C显示PGM图像(p5)中的直方图像素值,无需任何图像处理库,c,image,binary,pgm,C,Image,Binary,Pgm,这个问题很难理解使用纯C进行的图像处理。我用GCC编译的C编写了一个读取非二进制PGM文件的简单程序。现在,当我试图读取二进制PGM文件时,这就成了一个问题。可通过使用将JPG转换为PGM来获取该二进制PGM文件 注意:请不要使用任何图像处理库(例如:OpenCV)进行回答 我目前的代码是: #include <stdio.h> #include <stdlib.h> #define WIDTH 1024 #define HEIGHT 768 #defi
#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]);
}
}
#包括
#包括
#定义宽度1024
#定义高度768
#定义READ_IMAGE_NAME“MY_PGM_FILE_NAME.PGM”
无效打印柱状图表格(int*histog);
main(){
文件*fp;
int i,j,高度=高度,宽度=宽度;
字符行[100];
//颜色深度为255。
无符号字符像素值;
fp=fopen(读取图像名称,“r”);
//获取前四行。
fgets(第100行,fp);
fgets(第100行,fp);
fgets(第100行,fp);
fgets(第100行,fp);
//直方图辅助程序
国际历史[65536];
int x;
对于(x=0;x<65536;x++){
histo[x]=0;
}
对于(j=0;j和…问题是什么?您的代码在读取二进制PGM(P5?)时看起来几乎没有问题,只是缺少每个像素数据行的换行检查(根据wikipedia文章,ASCII和二进制格式在每个像素数据行的末尾都有换行符)
一些评论:
- 不要硬编码宽度和高度,应该使用标题中的信息
- 检查幻数,如果不是P5,则抛出/返回错误(或正确处理)
<> LI>文件可以有行注释,考虑
我上面的脚本无法显示正确的颜色直方图,因为如果你理性思考,你可能会得到100以上的像素颜色(不仅仅是100以下)。因此,主要问题是如何解决这个问题
我想你的意思是:
现在,在链接图像上运行此程序只会显示100以下像素值的非零直方图条目。我知道100以上的图像中至少有一个像素值,所以我的代码中有一个bug。有人能帮我弄清楚为什么会发生这种情况吗
我建议你重新措辞你的问题,以明确这一点
假设您只希望它对链接到的图像起作用,那么代码表面上看起来还可以。但是,可能会有很多小错误。以下是一些建议:
直方图大小
首先,你不能打印整个直方图。考虑将直方图大小传递给打印直方图的函数。此外,即使大小匹配(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]);
}
其他小问题
有很多事情不是由您的代码处理的:
PNM文件的开头可能有注释
行的长度可以超过100个字符
图像大小不强制为1024x768
在程序中硬编码文件名没有多大用处,即使只是为了测试代码
如果您实际得到的是每像素16位的灰度图像,则直方图足够大,但您应该读取2字节的值
关于您的计划的一些注意事项:
- 您应该读取标题,而不是硬编码宽度、高度和最大像素值
- 将整个图像加载到内存并从内存进行处理是一种更有效的方法
- PGM文件是二进制文件,您应该在fopen中使用“rb”(如果您在Windows上运行此文件,其中二进制文件与文本不同)
- 直方图打印函数缺少最后一个像素(255是有效的像素值)
- 不知道为什么直方图数组会变为64K,您是否也计划支持16位PGM
- 您应该进行错误处理,以避免崩溃或其他意外行为
下面是你的程序的改进版本,上面提到的几点。我希望它能有所帮助
#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);
}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
字符行[100];
整数宽度、高度、最大值;
无符号字符*图像;
无符号整数*历史;
int i;
文件*fd;
fd=fopen(argv[1],“rb”);
如果(fd==NULL){
printf(“无法打开图像文件\n”);
出口(1);
}
//幻数
fgets(行,sizeof(行),fd);
如果(strcmp(第“P5\n”行)!=0){
printf(“图像不是PGM格式!\n”);
fclose(fd);
出口(1);
}
//跳过评论
fgets(行,sizeof(行),fd);
//读标题
如果(fscanf(fd,“%d%d%d\n”、&宽度、高度和最大值)!=3){
printf(“无效标题\n”);
fclose(fd);
出口(1);
}
如果(最大值>255){
printf(“对不起,目前只支持8位PGM!\n”);
fclose(fd);
出口(1);
}
printf(“宽度:%d\n高度:%d\n最大值:%d\n”,宽度,高度,最大值);
//读取图像数据
图像=malloc(宽度*高度);
if(fread(图像,sizeof(无符号字符),宽度*高度,fd)!=宽度*高度){
printf(“无法读取图像\n”);
fclose(fd);
出口(1);
}
fclose(fd);
//计算直方图
histo=(int*)calloc(maxval+1,sizeof(int));
对于(i=0;i 对于(i=0;i好的,当我创建直方图读取颜色变化时,我无法得到任何合理的结果。我将提供我的PGM文件进行测试。顺便说一句,我的标题是我的问题。你没有读过吗?:)一个想法:尝试将其转换为ASCII格式(P2)并查看它,这应该检查您是否正确阅读了它not@exodream:标题可能是一个问题,但您似乎已经发布了一个解决方案。因此,我们唯一的问题已经回答,没有问题了。示例问题是:“当它应该执行“…”操作时,它在“情境”…“中的行为类似于“…”。有人能看到错误吗?”C/C++不是语言选择错误。您可以
#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);
}