這兩天在搞神經網絡,裏面的一我的臉數據庫的圖片格式是PGM,事實上以前早就知道了這個圖片格式,但是沒去深究這個圖片格式的數據到底是什麼安排的。搜索了下百度百科,發現介紹的真是簡單,如下就本身來系統地整理一下。 html
Jeremy Lin 數據庫
PGM是Portable Gray Map的縮寫。它是灰度圖像格式中一種最簡單的格式標準。另外兩種與之相近的圖片格式是PBM和PPM。它們分別相應着黑白圖像和彩色圖像。安全
PGM的數據存放方式相比於JPG來講是很是easy的,因爲它不進行數據壓縮。天然的PGM的圖片的大小也就比較大了。一個120*128 8-bit的灰度圖像,PGM的大小是44kb,而將這個圖片轉化爲JPG格式後。大小僅爲4kb。網絡
因此。在平常各類網絡應用中你是很是難見到PGM圖片的,它太浪費流量了。less
PGM的數據格式spa
就像上面說的,PGM是不進行數據壓縮的,那麼天然的。它的格式就很是直觀了。你可以直接用一個記事本打開它,只是記事本打開後換行沒了。很差看,如下用Sublime Text2打開:.net
看了上面的圖示,我想大部分都能猜出來一些東西了。code
PGM圖片的數據:orm
首先。以一個「Magic Number」來標識圖片格式,這個magic number是P2,不能是p2。或者P 2;htm
而後。第二行是圖片寬度、圖片高度,在上圖中是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