c++基于梯度算子(或Robert算子、或Prewitt算子锐化、或Sobel算子锐化)生成梯度图像,基于梯度图像利用边缘跟踪算法跟踪图像里的物体边缘,生成边缘图像。不使用opencv和matlabe
时间: 2023-12-29 10:05:40 浏览: 203
以下是一个 C++ 程序,使用 Sobel 算子进行图像锐化并生成边缘图像,不使用 OpenCV 和 MATLAB:
```c++
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
struct Image {
int width;
int height;
std::vector<unsigned char> data;
};
// 从文件中读取 PGM 格式图像
void readPGM(const std::string &filename, Image &image) {
std::ifstream file(filename, std::ios::binary);
if (!file.is_open()) {
std::cerr << "Error: Failed to open file " << filename << std::endl;
exit(1);
}
std::string magicNumber;
file >> magicNumber;
if (magicNumber != "P5") {
std::cerr << "Error: Not a PGM file" << std::endl;
exit(1);
}
file >> image.width;
file >> image.height;
int maxVal;
file >> maxVal;
if (maxVal > 255) {
std::cerr << "Error: Only 8-bit PGM files are supported" << std::endl;
exit(1);
}
file.get(); // 读取换行符
image.data.resize(image.width * image.height);
file.read(reinterpret_cast<char *>(image.data.data()), image.width * image.height);
}
// 保存 PGM 格式图像到文件
void writePGM(const std::string &filename, const Image &image) {
std::ofstream file(filename, std::ios::binary);
if (!file.is_open()) {
std::cerr << "Error: Failed to open file " << filename << std::endl;
exit(1);
}
file << "P5" << std::endl;
file << image.width << " " << image.height << std::endl;
file << "255" << std::endl;
file.write(reinterpret_cast<const char *>(image.data.data()), image.width * image.height);
}
// Sobel 算子计算梯度
void sobel(const Image &input, Image &output) {
int width = input.width;
int height = input.height;
std::vector<int> gx{-1, 0, 1, -2, 0, 2, -1, 0, 1};
std::vector<int> gy{-1, -2, -1, 0, 0, 0, 1, 2, 1};
output.width = width;
output.height = height;
output.data.resize(width * height);
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
int sumX = 0;
int sumY = 0;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
int pixel = static_cast<int>(input.data[(y + j) * width + (x + i)]);
sumX += gx[(j + 1) * 3 + (i + 1)] * pixel;
sumY += gy[(j + 1) * 3 + (i + 1)] * pixel;
}
}
int magnitude = static_cast<int>(std::sqrt(sumX * sumX + sumY * sumY));
output.data[y * width + x] = static_cast<unsigned char>(magnitude);
}
}
}
// 二值化图像
void threshold(const Image &input, Image &output, unsigned char thresholdValue) {
output.width = input.width;
output.height = input.height;
output.data.resize(input.width * input.height);
for (int i = 0; i < input.width * input.height; i++) {
output.data[i] = (input.data[i] >= thresholdValue) ? 255 : 0;
}
}
// 边缘跟踪算法
void edgeTrace(const Image &input, Image &output) {
int width = input.width;
int height = input.height;
output.width = width;
output.height = height;
output.data.resize(width * height);
std::vector<int> dx{-1, 0, 1, -1, 0, 1, -1, 0, 1};
std::vector<int> dy{-1, -1, -1, 0, 0, 0, 1, 1, 1};
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
if (input.data[y * width + x] == 0) {
continue;
}
bool isEdge = false;
for (int i = 0; i < 8; i++) {
int neighborX = x + dx[i];
int neighborY = y + dy[i];
if (input.data[neighborY * width + neighborX] == 255) {
isEdge = true;
break;
}
}
output.data[y * width + x] = isEdge ? 255 : 0;
}
}
}
int main(int argc, char *argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " input_image_path output_edge_image_path" << std::endl;
return 1;
}
// 读取输入图像
std::string inputImagePath = argv[1];
Image inputImage;
readPGM(inputImagePath, inputImage);
// 计算梯度
Image gradientImage;
sobel(inputImage, gradientImage);
// 二值化图像
Image thresholdImage;
threshold(gradientImage, thresholdImage, 128);
// 边缘跟踪
Image edgeImage;
edgeTrace(thresholdImage, edgeImage);
// 保存边缘图像
std::string outputImagePath = argv[2];
writePGM(outputImagePath, edgeImage);
return 0;
}
```
程序实现了 Sobel 算子的计算、图像的二值化和边缘跟踪算法。程序读取 PGM 格式图像,并将结果保存为 PGM 格式的边缘图像。
阅读全文