這兩天在搞神經網絡,里面的一個人臉數據庫的圖片格式是PGM,事實上之前早就知道了這個圖片格式,可是沒去深究這個圖片格式的數據究竟是什么安排的。搜索了下百度百科,發現介紹的真是簡單,以下就自己來系統地整理一下。
PGM是Portable Gray Map的縮寫。它是灰度圖像格式中一種最簡單的格式標准。另外兩種與之相近的圖片格式是PBM和PPM。它們分別相應着黑白圖像和彩色圖像。
PGM的數據存放方式相比於JPG來說是非常easy的,由於它不進行數據壓縮。自然的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
