PGM图片格式与代码

这两天在搞神经网络,里面的一个人脸数据库的图片格式是PGM,其实之前早就知道了这个图片格式,但是没去深究这个图片格式的数据到底是什么安排的。搜索了下百度百科,发现介绍的真是简单,下面就自己来系统地整理一下。                

Jeremy Lin 

PGM是Portable Gray Map的缩写,它是灰度图像格式中一种最简单的格式标准。另外两种与之相近的图片格式是PBM和PPM,它们分别对应着黑白图像和彩色图像。PGM的数据存放方式相比于JPG来说是非常简单的,因为它不进行数据压缩,自然的PGM的图片的大小也就比较大了。一个120*128 8-bit的灰度图像,PGM的大小是44kb,而将这个图片转化为JPG格式后,大小仅为4kb。所以,在日常各种网络应用中你是很难见到PGM图片的,它太浪费流量了。


PGM的数据格式

就像上面说的,PGM是不进行数据压缩的,那么自然的,它的格式就很直观了。你可以直接用一个记事本打开它,不过记事本打开后换行没了,不好看,下面用Sublime Text2打开:


看了上面的图示,我想大部分都能猜出来一些东西了。

PGM图片的数据

首先,以一个“Magic Number”来标识图片格式,这个magic number是P2,不能是p2,或者P 2;

然后,第二行是图片宽度、图片高度,在上图中是128和120;

第三行是这个图片数据的最大值,上图中是146;

最后,就是图片的像素数据值了,这些数据是以“row-major order”存放的,即是说按行存放的。当然,你认真看上图的话会发现,从第4行开始,每行都只有16个数据,默认情况下,每行长度不能超过70个字符,但是具体几个并没有要求,一种安全的做法是每行存放一个像素。

在有些PGM图片你可能会看到以#开头的行,这个是comment,比如说用#linjianmin.pgm来表示图片名称。


图片读取与创建代码:

#ifndef _PGM_

#define _PGM_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define ROWS(img)  ((img)->rows)
#define COLS(img)  ((img)->cols)
#define NAME(img)   ((img)->name)

typedef struct 
{
  char *name;
  int rows, cols;
  int *data;
} IMAGE;

char *img_basename(char *filename)
{
  char *newM, *part;
  int len, dex;

  len = strlen(filename);  
  dex = len - 1;
  while (dex > -1) 
  {
    if (filename[dex] == '/') 
	{
      break;
    } 
	else 
	{
      dex--;
    }
  }
  dex++;
  part = &(filename[dex]);
  len = strlen(part);
  newM = (char *) malloc ((unsigned) ((len + 1) * sizeof (char)));
  strcpy(newM, part);
  return(newM);
}


IMAGE *img_alloc()
{
  IMAGE *newM;

  newM = (IMAGE *) malloc (sizeof (IMAGE));
  if (newM == NULL) 
  {
    printf("IMGALLOC: Couldn't allocate image structure\n");
    return (NULL);
  }
  newM->rows = 0;
  newM->cols = 0;
  newM->name = NULL;
  newM->data = NULL;
  return (newM);
}


IMAGE *img_creat(char *name, int nr, int nc)
{
  int i, j;
  IMAGE *newM;

  newM = img_alloc();
  newM->data = (int *) malloc ((unsigned) (nr * nc * sizeof(int)));
  newM->name = img_basename(name);
  newM->rows = nr;
  newM->cols = nc;
  for (i = 0; i < nr; i++) 
  {
    for (j = 0; j < nc; j++) 
	{
      img_setpixel(newM, i, j, 0);
    }
  }
  return (newM);
}


void img_free(IMAGE* img)
{
  if (img->data) free ((char *) img->data);
  if (img->name) free ((char *) img->name);
  free ((char *) img);
}


void img_setpixel(IMAGE *img,int r, int c, int val)
{
  int nc;

  nc = img->cols;
  img->data[(r * nc) + c] = val;
}


int img_getpixel(IMAGE *img, int r, int c)
{
  int nc;

  nc = img->cols;
  return (img->data[(r * nc) + c]);
}


IMAGE *img_open(char *filename)
{
  IMAGE *newM;
  FILE *pgm;
  char line[512], intbuf[100], ch;
  int type, nc, nr, maxval, i, j, k, found;

  newM = img_alloc();
  if ((pgm = fopen(filename, "r")) == NULL) 
  {
    printf("IMGOPEN: Couldn't open '%s'\n", filename);
    return(NULL);
  }

  newM->name = img_basename(filename);

  /*** Scan pnm type information, expecting P5 ***/
  fgets(line, 511, pgm);
  sscanf(line, "P%d", &type);
  if (type != 5 && type != 2) 
  {
    printf("IMGOPEN: Only handles pgm files (type P5 or P2)\n");
    fclose(pgm);
    return(NULL);
  }

  /*** Get dimensions of pgm ***/
  fgets(line, 511, pgm);
  sscanf(line, "%d %d", &nc, &nr);
  newM->rows = nr;
  newM->cols = nc;

  /*** Get maxval ***/
  fgets(line, 511, pgm);
  sscanf(line, "%d", &maxval);
  if (maxval > 255) 
  {
    printf("IMGOPEN: Only handles pgm files of 8 bits or less\n");
    fclose(pgm);
    return(NULL);
  }

  newM->data = (int *) malloc ((unsigned) (nr * nc * sizeof(int)));
  if (newM->data == NULL) 
  {
    printf("IMGOPEN: Couldn't allocate space for image data\n");
    fclose(pgm);
    return(NULL);
  }

  if (type == 5) 
  {

    for (i = 0; i < nr; i++) {
      for (j = 0; j < nc; j++) {
        img_setpixel(newM, i, j, fgetc(pgm));
      }
    }

  } 
  else if (type == 2) 
  {

    for (i = 0; i < nr; i++) {
      for (j = 0; j < nc; j++) {

        k = 0;  found = 0;
        while (!found) {
          ch = (char) fgetc(pgm);
          if (ch >= '0' && ch <= '9') {
            intbuf[k] = ch;  k++;
  	  } else {
            if (k != 0) {
              intbuf[k] = '\0';
              found = 1;
	    }
	  }
	}
        img_setpixel(newM, i, j, atoi(intbuf));

      }
    }

  } else {
    printf("IMGOPEN: Fatal impossible error\n");
    fclose(pgm);
    return (NULL);
  }

  fclose(pgm);
  return (newM);
}


int img_write(IMAGE *img, char *filename)
{
  int i, j, nr, nc, k, val;
  FILE *iop;

  nr = img->rows;  nc = img->cols;
  iop = fopen(filename, "w");
  fprintf(iop, "P2\n");
  fprintf(iop, "%d %d\n", nc, nr);
  fprintf(iop, "255\n");

  k = 1;
  for (i = 0; i < nr; i++) {
    for (j = 0; j < nc; j++) {
      val = img_getpixel(img, i, j);
      if ((val < 0) || (val > 255)) {
        printf("IMG_WRITE: Found value %d at row %d col %d\n", val, i, j);
        printf("           Setting it to zero\n");
        val = 0;
      }
      if (k % 10) {
        fprintf(iop, "%d ", val);
      } else {
        fprintf(iop, "%d\n", val);
      }
      k++;
    }
  }
  fprintf(iop, "\n");
  fclose(iop);
  return (1);
}

#endif



本文地址:http://blog.csdn.net/linj_m/article/details/40477699

更多资源请关注 博客:LinJM-机器视觉  微博:林建民-机器视觉

Refs:

[1]http://netpbm.sourceforge.net/doc/pgm.html

[2]Netpbm format Wikipedia

  • 8
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要读取pgm文件数据,可以使用以下方法之一: 方法一:使用Pillow库 1. 导入必要的库:from PIL import Image 2. 使用Image.open()函数打开pgm文件:im = Image.open(filepath) 3. 查看图片格式:print(im.mode) 4. 查看图片尺寸:print(im.size) 5. 可以使用im对象的其他方法来操作和处理pgm文件数据。例如,可以使用im.show()来显示图片。 方法二:使用numpy和matplotlib库 1. 导入必要的库:import numpy as np, matplotlib.pyplot as plt 2. 定义一个函数来读取pgm文件数据: def read_pgm(pgmf): assert pgmf.readline() == 'P5\n' (width, height) = [int(i) for i in pgmf.readline().split()] depth = int(pgmf.readline()) assert depth <= 255 raster = [] for y in range(height): row = [] for x in range(width): row.append(ord(pgmf.read(1))) raster.append(row) return raster 3. 调用read_pgm函数并传入pgm文件路径来读取数据:data = read_pgm(filepath) 4. 可以使用numpy和matplotlib绘图库来显示pgm文件数据。例如,使用plt.imshow(np.array(data))来显示数据。 请注意,根据不同的pgm文件格式,你可能需要根据具体情况调整代码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [.pgm图片简介以及Python读取.pgm图片的方法](https://blog.csdn.net/quiet_girl/article/details/80904471)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [在python中读取.pgm格式图像](https://blog.csdn.net/l_z_z_z/article/details/120800683)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值