最近業務需要將 matlab中bwlookup 的轉C
這個函數沒有現成的m文件參考,內置已經打成庫了,所以沒有參考源代碼
但是它的解釋還是很清楚的,可以根據這個來寫
Nonlinear filtering using lookup tables - MATLAB bwlookup - MathWorks 中國
A?= bwlookup(B,lut)
?performs a 2-by-2 or 3-by-3 nonlinear neighborhood filtering operation on binary image?BW
. The neighborhood processing determines an integer index value used to access values in lookup table?lut
. The fetched?lut
?value becomes the pixel value in output image?A
?at the targeted position.
它說的很清楚,BW是二值圖像矩陣,lut是一個512的查找表,對3*3鄰居矩陣進行一些濾波(權重和)得到最后結果
用GPT生成一個
#include <stdio.h>
#include <stdlib.h>#define WIDTH 3
#define HEIGHT 3// 將 3x3 鄰域編碼為一個 9 位二進制數
int encodeNeighborhood(int neighborhood[3][3]) {int code = 0;for (int i = 0; i < 3; ++i) {for (int j = 0; j < 3; ++j) {code = (code << 1) | neighborhood[i][j];}}return code;
}// 應用查找表進行形態學操作
void bwlookup(int input[HEIGHT][WIDTH], int output[HEIGHT][WIDTH], int lut[512]) {int neighborhood[3][3];// 處理內部像素for (int y = 1; y < HEIGHT - 1; ++y) {for (int x = 1; x < WIDTH - 1; ++x) {// 提取 3x3 鄰域for (int i = -1; i <= 1; ++i) {for (int j = -1; j <= 1; ++j) {neighborhood[i + 1][j + 1] = input[y + i][x + j];}}// 使用查找表進行轉換int code = encodeNeighborhood(neighborhood);output[y][x] = lut[code];}}// 處理邊緣像素 (拷貝原始值)for (int x = 0; x < WIDTH; ++x) {output[0][x] = input[0][x];output[HEIGHT-1][x] = input[HEIGHT-1][x];}for (int y = 0; y < HEIGHT; ++y) {output[y][0] = input[y][0];output[y][WIDTH-1] = input[y][WIDTH-1];}
}int main() {// 示例二值圖像 (3x3)int input[HEIGHT][WIDTH] = {{1, 0, 1},{0, 1, 0},{1, 0, 1}};// 初始化輸出圖像int output[HEIGHT][WIDTH] = {0};// 示例查找表int lut[512] = {0};lut[2] = 1; // 設定特定模式的輸出值// 應用 bwlookupbwlookup(input, output, lut);// 打印結果圖像for (int y = 0; y < HEIGHT; ++y) {for (int x = 0; x < WIDTH; ++x) {printf("%d ", output[y][x]);}printf("\n");}return 0;
}
?顯然它給的矩陣濾波器順序搞錯了,它的順序是
這是行優先,我本來理解為要列優先,其實人matlab代碼給出解釋了(包括網頁)
手動改動下?
仔細觀察,
這給地方還有一個加1,c代碼中求和一樣的code,沒有加1,原因是這里做index的時候,c是從0開始,index本身比matlab就要少1
這樣計算出來發現還不對,仔細對比,中心數據都對上了,發現還是邊緣不對
matlab中的原矩陣需要擴展,擴展的地方都要填0,然后只取中間
把想法交給GPT,讓他生成把
#include <stdio.h>#define HEIGHT 5
#define WIDTH 5// 將 3x3 鄰域編碼為一個 9 位二進制數
int encodeNeighborhood(int arr[3][3]) {int code = 0;for (int i = 0; i < 3; ++i) {for (int j = 0; j < 3; ++j) {code |= (arr[i][j] << (i * 3 + j));}}return code;
}// 應用查找表進行形態學操作
void bwlookup(int input[HEIGHT][WIDTH], int output[HEIGHT][WIDTH], int lut[512]) {int extendedInput[HEIGHT + 2][WIDTH + 2] = {0}; // 擴展后的輸入數組,初始化為零int neighborhood[3][3];// 將原始輸入復制到擴展后的數組中for (int y = 0; y < HEIGHT; ++y) {for (int x = 0; x < WIDTH; ++x) {extendedInput[y + 1][x + 1] = input[y][x];}}// 對擴展后的數組應用形態學操作for (int y = 1; y < HEIGHT + 1; ++y) {for (int x = 1; x < WIDTH + 1; ++x) {// 提取 3x3 鄰域for (int i = -1; i <= 1; ++i) {for (int j = -1; j <= 1; ++j) {neighborhood[i + 1][j + 1] = extendedInput[y + i][x + j];}}// 使用查找表進行轉換int code = encodeNeighborhood(neighborhood);output[y - 1][x - 1] = lut[code];}}
}// 測試函數
int main() {int input[HEIGHT][WIDTH] = {{0, 0, 0, 0, 0},{0, 1, 1, 1, 0},{0, 1, 1, 1, 0},{0, 1, 1, 1, 0},{0, 0, 0, 0, 0}};int output[HEIGHT][WIDTH] = {0}; // 初始化輸出數組int lut[512]; // 查找表// 初始化查找表 (這里假設查找表已定義)for (int i = 0; i < 512; ++i) {lut[i] = 1; // 這里只是一個示例,你應該根據實際需求初始化查找表}// 應用形態學操作bwlookup(input, output, lut);// 打印輸出printf("輸出:\n");for (int y = 0; y < HEIGHT; ++y) {for (int x = 0; x < WIDTH; ++x) {printf("%d ", output[y][x]);}printf("\n");}return 0;
}