基本上我的问题是我应用索贝尔过滤器到BMP图像,其中1像素是1位。但它没有做任何事情的图像,而过滤水平。
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;
}
我目前的图像:
水平过滤器:
this is horizontally
立式过滤器:
This is vertically
两者合在一起:
This is both together
我尝试了几乎每一个差分滤波器,但问题是一样的。也许我读错或写错了图像。但仍然垂直的滤波器工作。
1条答案
按热度按时间bvuwiixz1#
问题似乎是存储
Gx
时缺少abs
:将
outputX[y][x] = Gx
替换为outputX[y][x] = abs(Gx)
。我们最好也将最大值裁剪为
255
:我试图重现这个问题,但我在阅读写BMP图像时遇到了问题。
我使用OpenCV
cv::imread
和cv::imwrite
进行阅读。我使用了“水平过滤器”图像从您的职位作为一个输入。
我无法重现该问题(可能是由于不同的输入)。
完整代码:
differentialX.bmp
(PNG格式):differentialY.bmp
(PNG格式):