You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单比特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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:13:13