单比特BMP图像Sobel水平滤波无效问题求助
问题描述
对单像素为1比特的BMP图像应用Sobel滤波器时,垂直滤波可正常工作,但水平滤波无任何效果。尝试多种差分滤波器后问题依旧,怀疑图像读写逻辑存在错误。
Sobel滤波函数
void sobelFilter(unsigned char** image, int width, int height) { const int vertical_kernel[3][3] = { {-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1} }; const int horizontal_kernel[3][3] = { {1, 2, 1}, {0, 0, 0}, {-1, -2, -1} }; unsigned char** outputX = new unsigned char* [height]; for (int i = 0; i < height; i++) { outputX[i] = new unsigned char[width]; } unsigned char** outputY = new unsigned char* [height]; for (int i = 0; i < height; i++) { outputY[i] = new unsigned char[width]; } unsigned char** filteredImage = new unsigned char* [height]; for (int i = 0; i < height; i++) { filteredImage[i] = new unsigned char[width]; } int Gx, Gy, G; for (int y = 1; y < height - 1; ++y) { for (int x = 1; x < width - 1; ++x) { Gx = image[y - 1][x + 1] + 2 * image[y][x + 1] + image[y + 1][x + 1] - image[y - 1][x - 1] - 2 * image[y][x - 1] - image[y + 1][x - 1]; Gy = image[y + 1][x - 1] + 2 * image[y + 1][x] + image[y + 1][x + 1] - image[y - 1][x - 1] - 2 * image[y - 1][x] - image[y - 1][x + 1]; G = abs(Gx) + abs(Gy); G = min(max(G, 0), 255); outputY[y][x] = abs(Gy); outputX[y][x] = Gx; filteredImage[y][x] = G; } } writeDataToFile(outputY, width, height, (char*)"differentialY.bmp"); writeDataToFile(outputX, width, height, (char*)"differentialX.bmp"); writeDataToFile(filteredImage, width, height, (char*)"differential.bmp"); }
完整代码
#include <iostream> #include <fstream> #include <algorithm> #include <cmath> using namespace std; void readHeaderOfAnImage(char* header, int headerSize, char* fileName) { ifstream fin(fileName, ios::binary); fin.read(header, headerSize); fin.close(); } void readFileData(unsigned char** imageData, int width, int height, int headerSize, char* fileName) { ifstream fin(fileName, ios::binary); fin.ignore(headerSize); int padding = 4 - ((width / 8) % 4); unsigned char buffer = fin.get(); for (int i = 0, counter = 0; i < height; i++) { for (int j = 0; j < width; j++) { imageData[i][j] = buffer & (128 >> counter); ++counter; if (counter == 8) { buffer = fin.get(); counter = 0; } } for (int k = 0; k < padding; ++k) fin.get(); } fin.close(); } void writeHeaderOfAnImage(char* header, int headerSize, char* fileName) { ofstream fout(fileName, ios::binary); fout.write(header, headerSize); fout.close(); } void writeDataToFile(unsigned char** imageData, int width, int height, char* fileName) { ofstream fout(fileName, ios::app | ios::binary); int padding = 4 - ((width / 8) % 4); unsigned char buffer = 0; for (int i = 0, counter = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (counter == 8) {//bit ended, need new one fout.put(buffer); counter = 0; buffer = 0; } if (imageData[i][j]) buffer = buffer | (1 << (7 - counter));//black pixel? counter++; } for (int k = 0; k < padding; k++) //need padding for (int m = 0; m < 8; m++) { if (counter == 8) { fout.put(buffer); counter = 0; buffer = 0; } counter++; } if (counter == 8) { fout.put(buffer); counter = 0; buffer = 0; } } fout.close(); } unsigned char findMedian(unsigned char arr[], int n) { sort(arr, arr + n); return arr[n / 2]; } void medianFilter(unsigned char** imageData, unsigned char ** medianFilteredImageData, int width, int height) { const int kernel = 3; for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) { unsigned char window[kernel * kernel]; int k = 0; for (int x = i - kernel / 2; x <= i + kernel / 2; x++) { for (int y = j - kernel / 2; y <= j + kernel / 2; y++) { if (x >= 0 && x < height && y >= 0 && y < width) { window[k] = imageData[x][y]; k++; } } } medianFilteredImageData[i][j] = findMedian(window, k); } } } int main() { const int width = 3000, height = 3000, headerSize = 62; char imageToReadFrom[256], imageToWriteInAfterMedian[256] = "median.bmp", imageToWriteInAfterDifferential[256] = "differential.bmp"; cout << "Write the name of image that you want to read:\n"; cin >> imageToReadFrom; char* header = new char[headerSize]; unsigned char** imageData = new unsigned char* [height]; for (int i = 0; i < height; i++) imageData[i] = new unsigned char[width]; unsigned char** medianFilteredImageData = new unsigned char* [height]; for (int i = 0; i < height; i++) medianFilteredImageData[i] = new unsigned char[width]; readHeaderOfAnImage(header, headerSize, imageToReadFrom); readFileData(imageData, width, height, headerSize, imageToReadFrom); medianFilter(imageData, medianFilteredImageData, width, height); writeHeaderOfAnImage(header, headerSize, imageToWriteInAfterMedian); writeDataToFile(medianFilteredImageData, width, height, imageToWriteInAfterMedian); writeHeaderOfAnImage(header, headerSize, imageToWriteInAfterDifferential); writeHeaderOfAnImage(header, headerSize, (char*)"differentialY.bmp"); writeHeaderOfAnImage(header, headerSize, (char*)"differentialX.bmp"); sobelFilter(medianFilteredImageData, width, height); cout << "Ended"; return 0; }
滤波结果
- 水平滤波效果:图像无明显变化,未检测出水平边缘
- 垂直滤波效果:成功检测出图像中的垂直边缘
- 两者结合效果:仅呈现垂直边缘检测结果,无水平边缘信息
内容的提问来源于Stack Exchange,提问作者NiKiTjA_OFF
相关产品推荐
相关产品推荐

