影象資訊處理實驗二
阿新 • • 發佈:2019-01-06
要求:
1. Image binarization
2. Binary image erosion
3. Binary image delation
4. Binary image opening
5. Binary image closing
#include <stdio.h> #include <Windows.h> void ToRGB(char* a, char* b) { BITMAPFILEHEADER fileHeader;// 點陣圖檔案頭 BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭 FILE* pFile = fopen(a, "rb"); if (pFile == NULL) { printf("開啟點陣圖失敗\n"); exit(-1); } fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //讀取檔案頭 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //讀取資訊頭 WORD bitCount = infoHeader.biBitCount; //顏色位數 if (bitCount == 16) { exit(-1); } int Clr = 0; RGBQUAD *QUAD = NULL; if (bitCount < 16) { Clr = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount; if (Clr>256) Clr = 0; } // 讀取調色盤 int i = 0, j = 0; if (Clr > 0) { QUAD = (RGBQUAD*)malloc(sizeof(RGBQUAD)*Clr); fread(QUAD, sizeof(RGBQUAD)*Clr, 1, pFile); for (i = 0; i < Clr; i++) { QUAD[i].rgbRed = QUAD[i].rgbBlue = QUAD[i].rgbGreen = (BYTE)(0.3 * QUAD[i].rgbRed + 0.59 * QUAD[i].rgbGreen + 0.11 * QUAD[i].rgbBlue); } } LONG pW = infoHeader.biWidth; //影象資料的寬度 LONG pH = infoHeader.biHeight; //影象資料的高度 int pSize = ((pW * bitCount)>>3)*pH; //影象資料大小 BYTE* P = (BYTE*)malloc(pSize); //申請空間儲存影象資料 int LineSize = ((pW * bitCount)>> 3); //行資料大小 fread(P, pSize, 1, pFile); //存入影象資料 if (Clr == 0) { for (i = 0; i < pH; i++)//行 { if (bitCount == 24) { for (j = 0; j < pW * 3; j = j + 3)// 列,因為每個畫素佔3個位元組 { int n = i*LineSize + j; int r = P[n]; int g = P[n+1]; int b = P[n + 2]; int y = 0.299*r + 0.587*g + 0.114*b; int u = 0.492*(b - y); int v = 0.877*(r - y); y = y + 31; //把所有畫素點的y增大31 /*if (y > 255) //如果越界則置為255 y = 255; if (y < 0) y = 0; if (u > 255) //如果越界則置為255 u = 255; if (u < 0) u = 0; if (v > 255) //如果越界則置為255 v = 255; if (v < 0) v = 0; */ int R = y + 1.14*v; int G = y -0.394*u - 0.581*v; int B = y + 2.032*u; if (R > 255) //R如果越界則置為255 R = 255; if (R < 0) R = 0; if (G > 255) //如果越界則置為255 G = 255; if (G < 0) G = 0; if (B > 255) //如果越界則置為255 B = 255; if (B < 0) B = 0; P[n] = (BYTE)(R); //分別是新r.g.b分量 P[n + 1] = (BYTE)(G); P[n + 2] = (BYTE)(B); } } } } FILE* dFile = fopen(b, "wb");//建立目標檔案 fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //寫入檔案頭 fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //寫入檔案資訊頭 if (QUAD) { fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile); } //寫入影象資料 fwrite(P, pSize, 1, dFile); fclose(dFile); if (QUAD) { free(QUAD); QUAD = NULL; } if (P) { free(P); P=NULL; } } void ToGrey(char* a, char* b) { BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案 BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭 FILE* pFile = fopen(a, "rb"); if (pFile == NULL) { printf("開啟檔案失敗\n"); exit(-1); } // 讀取頭資訊 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //讀取檔案頭 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //讀取資訊頭 WORD bitCount = infoHeader.biBitCount;//色彩的位數 if (bitCount == 16) { exit(-1); } int Clr = 0; RGBQUAD *QUAD = NULL; if (bitCount < 16) { Clr = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount; if (Clr>256) Clr = 0; } // 讀取調色盤 int i = 0, j = 0; if (Clr > 0) { QUAD = (RGBQUAD*)malloc(sizeof(RGBQUAD)*Clr); fread(QUAD, sizeof(RGBQUAD)*Clr, 1, pFile); for (i = 0; i < Clr; i++) { QUAD[i].rgbRed = QUAD[i].rgbBlue = QUAD[i].rgbGreen = (BYTE)(0.3 * QUAD[i].rgbRed + 0.59 * QUAD[i].rgbGreen + 0.11 * QUAD[i].rgbBlue); //灰度影象三個都是y } } LONG pW = infoHeader.biWidth; //影象資料的寬度 LONG pH = infoHeader.biHeight; //影象資料的高度 int pSize = ((pW * bitCount)>>3)*pH; //影象資料大小 BYTE* P = (BYTE*)malloc(pSize); //申請空間儲存影象資料 int LineSize = ((pW * bitCount)>> 3); //行資料大小 fread(P, pSize, 1, pFile); //存入影象資料 for(i = 0; i < pH; i++)//行 { for (j = 0; j < pW*3; j = j + 3)// 列 { int n = i*LineSize + j; if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120) P[n] = P[n + 1] = P[n + 2] = (BYTE)255; else P[n] = P[n + 1] = P[n + 2] = (BYTE)0; } } FILE* dFile = fopen(b, "wb");//建立目標檔案 fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //寫入檔案頭 fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //寫入檔案資訊頭 if (QUAD) { fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile); } //寫入影象資料 fwrite(P, pSize, 1, dFile); fclose(dFile); if (QUAD) { free(QUAD); QUAD = NULL; } if (P) { free(P); P = NULL; } } void Delation(char* a, char* b) { BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案 BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭 FILE* pFile = fopen(a, "rb"); if (pFile == NULL) { printf("開啟檔案失敗\n"); exit(-1); } // 讀取頭資訊 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //讀取檔案頭 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //讀取資訊頭 WORD bitCount = infoHeader.biBitCount;//色彩的位數 int Clr = 0; RGBQUAD *QUAD = NULL; int i = 0, j = 0; LONG pW = infoHeader.biWidth; //影象資料的寬度 LONG pH = infoHeader.biHeight; //影象資料的高度 int pSize = ((pW * bitCount)>>3)*pH; //影象資料大小 BYTE* P = (BYTE*)malloc(pSize); //申請空間儲存影象資料 int LineSize = ((pW * bitCount)>> 3); //行資料大小 fread(P, pSize, 1, pFile); //存入影象資料 //先二值化 for(i = 0; i < pH; i++)//行 { for (j = 0; j < pW*3; j = j + 3)// 列 { int n = i*LineSize + j; if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120) P[n] = P[n + 1] = P[n + 2] = (BYTE)255; else P[n] = P[n + 1] = P[n + 2] = (BYTE)0; } } //再delation int width=3,height=3; int mid=(width+1)/2-1; int p,q; int n; BYTE v = 255; for(i = mid; i < pH - mid; i++)//行 { for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列 { for(p = 0; p < height; p++) { for(q = 0; q < width * 3; q = q + 3) { if(p == mid && q == mid) continue; n=(i+p)*LineSize + (j+q); v &= P[n]; } } n = i * LineSize + j; P[n] = P[n + 1] = P[n + 2] = v; v = 255; } } FILE* dFile = fopen(b, "wb");//建立目標檔案 fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //寫入檔案頭 fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //寫入檔案資訊頭 if (QUAD) { fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile); } //寫入影象資料 fwrite(P, pSize, 1, dFile); fclose(dFile); if (QUAD) { free(QUAD); QUAD = NULL; } if (P) { free(P); P = NULL; } } void Erosion(char* a, char* b) { BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案 BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭 FILE* pFile = fopen(a, "rb"); // 讀取頭資訊 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //讀取檔案頭 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //讀取資訊頭 WORD bitCount = infoHeader.biBitCount;//色彩的位數 int Clr = 0; RGBQUAD *QUAD = NULL; int i = 0, j = 0; LONG pW = infoHeader.biWidth; //影象資料的寬度 LONG pH = infoHeader.biHeight; //影象資料的高度 int pSize = ((pW * bitCount)>>3)*pH; //影象資料大小 BYTE* P = (BYTE*)malloc(pSize); //申請空間儲存影象資料 int LineSize = ((pW * bitCount)>> 3); //行資料大小 fread(P, pSize, 1, pFile); //存入影象資料 //先二值化 for(i = 0; i < pH; i++)//行 { for (j = 0; j < pW*3; j = j + 3)// 列 { int n = i*LineSize + j; if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120) P[n] = P[n + 1] = P[n + 2] = (BYTE)255; else P[n] = P[n + 1] = P[n + 2] = (BYTE)0; } } //再erosion int width=3,height=3; int mid=(width+1)/2-1; int p,q; int n; BYTE v = 0; for(i = mid; i < pH - mid; i++)//行 { for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列 { for(p = 0; p < height; p++) { for(q = 0; q < width * 3; q = q + 3) { if(p == mid && q == mid) continue; n=(i+p)*LineSize + (j+q); v |= P[n]; } } n = i * LineSize + j; P[n] = P[n + 1] = P[n + 2] = v; v = 0; } } FILE* dFile = fopen(b, "wb");//建立目標檔案 fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //寫入檔案頭 fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //寫入檔案資訊頭 if (QUAD) { fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile); } //寫入影象資料 fwrite(P, pSize, 1, dFile); fclose(dFile); if (QUAD) { free(QUAD); QUAD = NULL; } if (P) { free(P); P = NULL; } } void Opening(char* a, char* b) { BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案 BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭 FILE* pFile = fopen(a, "rb"); // 讀取頭資訊 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //讀取檔案頭 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //讀取資訊頭 WORD bitCount = infoHeader.biBitCount;//色彩的位數 int Clr = 0; RGBQUAD *QUAD = NULL; int i = 0, j = 0; LONG pW = infoHeader.biWidth; //影象資料的寬度 LONG pH = infoHeader.biHeight; //影象資料的高度 int pSize = ((pW * bitCount)>>3)*pH; //影象資料大小 BYTE* P = (BYTE*)malloc(pSize); //申請空間儲存影象資料 int LineSize = ((pW * bitCount)>> 3); //行資料大小 fread(P, pSize, 1, pFile); //存入影象資料 //先二值化 for(i = 0; i < pH; i++)//行 { for (j = 0; j < pW*3; j = j + 3)// 列 { int n = i*LineSize + j; if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120) P[n] = P[n + 1] = P[n + 2] = (BYTE)255; else P[n] = P[n + 1] = P[n + 2] = (BYTE)0; } } //再erosion int width=3,height=3; int mid=(width+1)/2-1; int p,q; int n; BYTE v = 0; for(i = mid; i < pH - mid; i++)//行 { for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列 { for(p = 0; p < height; p++) { for(q = 0; q < width * 3; q = q + 3) { if(p == mid && q == mid) continue; n=(i+p)*LineSize + (j+q); v |= P[n]; } } n = i * LineSize + j; P[n] = P[n + 1] = P[n + 2] = v; v = 0; } } //再Delation v = 255; for(i = mid; i < pH - mid; i++)//行 { for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列 { for(p = 0; p < height; p++) { for(q = 0; q < width * 3; q = q + 3) { if(p == mid && q == mid) continue; n=(i+p)*LineSize + (j+q); v &= P[n]; } } n = i * LineSize + j; P[n] = P[n + 1] = P[n + 2] = v; v = 255; } } FILE* dFile = fopen(b, "wb");//建立目標檔案 fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //寫入檔案頭 fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //寫入檔案資訊頭 if (QUAD) { fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile); } //寫入影象資料 fwrite(P, pSize, 1, dFile); fclose(dFile); if (QUAD) { free(QUAD); QUAD = NULL; } if (P) { free(P); P = NULL; } } void Closing(char* a, char* b) { BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案 BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭 FILE* pFile = fopen(a, "rb"); // 讀取頭資訊 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //讀取檔案頭 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //讀取資訊頭 WORD bitCount = infoHeader.biBitCount;//色彩的位數 int Clr = 0; RGBQUAD *QUAD = NULL; int i = 0, j = 0; LONG pW = infoHeader.biWidth; //影象資料的寬度 LONG pH = infoHeader.biHeight; //影象資料的高度 int pSize = ((pW * bitCount)>>3)*pH; //影象資料大小 BYTE* P = (BYTE*)malloc(pSize); //申請空間儲存影象資料 int LineSize = ((pW * bitCount)>> 3); //行資料大小 fread(P, pSize, 1, pFile); //存入影象資料 //先二值化 for(i = 0; i < pH; i++)//行 { for (j = 0; j < pW*3; j = j + 3)// 列 { int n = i*LineSize + j; if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120) P[n] = P[n + 1] = P[n + 2] = (BYTE)255; else P[n] = P[n + 1] = P[n + 2] = (BYTE)0; } } //先Delation int width=3,height=3; int mid=(width+1)/2-1; int p,q; int n; BYTE v = 255; for(i = mid; i < pH - mid; i++)//行 { for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列 { for(p = 0; p < height; p++) { for(q = 0; q < width * 3; q = q + 3) { if(p == mid && q == mid) continue; n=(i+p)*LineSize + (j+q); v &= P[n]; } } n = i * LineSize + j; P[n] = P[n + 1] = P[n + 2] = v; v = 255; } } //再erosion v = 0; for(i = mid; i < pH - mid; i++)//行 { for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列 { for(p = 0; p < height; p++) { for(q = 0; q < width * 3; q = q + 3) { if(p == mid && q == mid) continue; n=(i+p)*LineSize + (j+q); v |= P[n]; } } n = i * LineSize + j; P[n] = P[n + 1] = P[n + 2] = v; v = 0; } } FILE* dFile = fopen(b, "wb");//建立目標檔案 fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //寫入檔案頭 fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //寫入檔案資訊頭 if (QUAD) { fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile); } //寫入影象資料 fwrite(P, pSize, 1, dFile); fclose(dFile); if (QUAD) { free(QUAD); QUAD = NULL; } if (P) { free(P); P = NULL; } } int main() { ToGrey("d.bmp", "grayd.bmp"); ToRGB("d.bmp", "rgbd.bmp"); Erosion("d.bmp", "erosiond.bmp"); Delation("d.bmp","delationd.bmp"); Opening("d.bmp","opend.bmp"); Closing("d.bmp","closed.bmp"); return 0; }