2301_76655155 2023-06-16 22:01 采纳率: 100%
浏览 170
已结题

用c语言完成基于数学形态学的边缘检测。

必做: bmp图像读取,二值形态学边缘检测,灰度形态学边缘检测。读取bmp图像后,对图像进行边缘检测,并将边缘图像保存为新的bmp图像

  • 写回答

8条回答 默认 最新

  • Watch the clown 2023-06-16 23:49
    关注

    我尝试了你的边缘图像,需要告诉你心目中的图像特征要多细腻,我研究图像很多年,总的来说c语言实现效果达不到那么完美,最好要用OpenCV和libbmp实现,边缘检测是得靠模型不断训练得到的,我保留意见
    原图

    img

    生成图

    img

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    #pragma pack(1)
    
    typedef struct {
        unsigned char magic[2];
        unsigned int fileSize;
        unsigned short reserved1;
        unsigned short reserved2;
        unsigned int offset;
    } BMPHeader;
    
    typedef struct {
        unsigned int headerSize;
        int width;
        int height;
        unsigned short planes;
        unsigned short bitsPerPixel;
        unsigned int compression;
        unsigned int imageSize;
        int xPixelsPerMeter;
        int yPixelsPerMeter;
        unsigned int colorsUsed;
        unsigned int colorsImportant;
    } BMPInfoHeader;
    
    typedef struct {
        unsigned char blue;
        unsigned char green;
        unsigned char red;
    } RGB;
    
    void readBmp(const char* filename, RGB** image, int* width, int* height) {
        FILE* fp = fopen(filename, "rb");
        if (!fp) {
            printf("Failed to open file: %s\n", filename);
            exit(1);
        }
    
        BMPHeader header;
        BMPInfoHeader infoHeader;
    
        if (fread(&header, sizeof(header), 1, fp) != 1) {
            printf("Failed to read BMP header\n");
            exit(1);
        }
    
        if (fread(&infoHeader, sizeof(infoHeader), 1, fp) != 1) {
            printf("Failed to read BMP info header\n");
            exit(1);
        }
    
        if (header.magic[0] != 'B' || header.magic[1] != 'M') {
            printf("Invalid BMP magic number: %c%c\n", header.magic[0], header.magic[1]);
            exit(1);
        }
    
        if (infoHeader.bitsPerPixel != 24) {
            printf("Unsupported BMP format: %d bits per pixel\n", infoHeader.bitsPerPixel);
            exit(1);
        }
    
        if (infoHeader.compression != 0) {
            printf("Unsupported BMP compression method: %d\n", infoHeader.compression);
            exit(1);
        }
    
        *width = infoHeader.width;
        *height = infoHeader.height;
    
        *image = (RGB*)malloc(*width * *height * sizeof(RGB));
        if (!*image) {
            printf("Memory allocation failed\n");
            exit(1);
        }
    
        int rowSize = (*width * 3 + 3) / 4 * 4 - (*width * 3 % 4);
    
        int i, j;
        for (i = 0; i < *height; i++) {
            for (j = 0; j < *width; j++) {
                RGB pixel;
                if (fread(&pixel, sizeof(pixel), 1, fp) != 1) {
                    printf("Failed to read pixel at (%d, %d)\n", j, i);
                    exit(1);
                }
                (*image)[(*height - i - 1) * *width + j] = pixel;
            }
            fseek(fp, rowSize - *width * 3, SEEK_CUR);
        }
    
        fclose(fp);
    }
    
    void saveBmp(const char* filename, RGB* image, int width, int height) {
        FILE* fp = fopen(filename, "wb");
        if (!fp) {
            printf("Failed to create file: %s\n", filename);
            exit(1);
        }
    
        BMPHeader header;
        BMPInfoHeader infoHeader;
    
        header.magic[0] = 'B';
        header.magic[1] = 'M';
        header.fileSize = sizeof(header) + sizeof(infoHeader) + (width * height * 3);
        header.reserved1 = 0;
        header.reserved2 = 0;
        header.offset = sizeof(header) + sizeof(infoHeader);
    
        infoHeader.headerSize = sizeof(infoHeader);
        infoHeader.width = width;
        infoHeader.height = height;
        infoHeader.planes = 1;
        infoHeader.bitsPerPixel = 24;
        infoHeader.compression = 0;
        infoHeader.imageSize = width * height * 3;
        infoHeader.xPixelsPerMeter = 0;
        infoHeader.yPixelsPerMeter = 0;
        infoHeader.colorsUsed = 0;
        infoHeader.colorsImportant = 0;
    
        if (fwrite(&header, sizeof(header), 1, fp) != 1) {
            printf("Failed to write BMP header\n");
            exit(1);
        }
    
        if (fwrite(&infoHeader, sizeof(infoHeader), 1, fp) != 1) {
            printf("Failed to write BMP info header\n");
            exit(1);
        }
    
        int rowSize = (width * 3 + 3) / 4 * 4 - (width * 3 % 4);
    
        int i, j;
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                RGB pixel = image[(height - i - 1) * width + j];
                if (fwrite(&pixel, sizeof(pixel), 1, fp) != 1) {
                    printf("Failed to write pixel at (%d, %d)\n", j, i);
                    exit(1);
                }
            }
            unsigned char padding[3] = {0};
            if (fwrite(padding, sizeof(padding), 1, fp) != 1) {
                printf("Failed to write padding\n");
                exit(1);
            }
        }
    
        fclose(fp);
    
        printf("图像处理成功!\n");
    }
    
    void gray(RGB* image, int width, int height) {
        int i, j;
    
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                unsigned char gray = (unsigned char)(0.299 * image[width*i + j].red + 0.587 * image[width*i + j].green + 0.114 * image[width*i + j].blue);
                image[width*i + j].red = gray;
                image[width*i + j].green = gray;
                image[width*i + j].blue = gray;
            }
        }
    }
    
    void binarize(RGB* image, int width, int height) {
        int i, j;
    
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                unsigned char gray = image[width*i + j].red;
                if (gray < 128) {
                    image[width*i + j].red = 0;
                    image[width*i + j].green = 0;
                    image[width*i + j].blue = 0;
                }
                else {
                    image[width*i + j].red = 255;
                    image[width*i + j].green = 255;
                    image[width*i + j].blue = 255;
                }
            }
        }
    }
    
    void dilate(RGB* image, int width, int height) {
        int i, j, k, l, m, n;
        RGB* temp = (RGB*)malloc(width*height * sizeof(RGB));
        if (!temp) {
            printf("Memory allocation failed\n");
            exit(1);
        }
    
        memcpy(temp, image, width*height * sizeof(RGB));
    
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                int flag = 1;
                for (k = -1; k <= 1; k++) {
                    for (l = -1; l <= 1; l++) {
                        m = i + k;
                        n = j + l;
                        if (m >= 0 && m < height && n >= 0 && n < width) {
                            if (temp[width*m + n].red == 0) {
                                flag = 0;
                                break;
                            }
                        }
                    }
                    if (!flag) {
                        break;
                    }
                }
                if (flag) {
                    image[width*i + j].red = 0;
                    image[width*i + j].green = 0;
                    image[width*i + j].blue = 0;
                }
            }
        }
    
        free(temp);
    }
    
    void erode(RGB* image, int width, int height) {
        int i, j, k, l, m, n;
        RGB* temp = (RGB*)malloc(width*height * sizeof(RGB));
        if (!temp) {
            printf("Memory allocation failed\n");
            exit(1);
        }
    
        memcpy(temp, image, width*height * sizeof(RGB));
    
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                int flag = 1;
                for (k = -1; k <= 1; k++) {
                    for (l = -1; l <= 1; l++) {
                        m = i + k;
                        n = j + l;
                        if (m >= 0 && m < height && n >= 0 && n < width) {
                            if (temp[width*m + n].red == 255) {
                                flag = 0;
                                break;
                            }
                        }
                    }
                    if (!flag) {
                        break;
                    }
                }
                if (flag) {
                    image[width*i + j].red = 255;
                    image[width*i + j].green = 255;
                    image[width*i + j].blue = 255;
                }
            }
        }
    
        free(temp);
    }
    
    void edgeDetection(RGB* image, int width, int height) {
        int i, j, k, l, m, n;
        RGB* temp = (RGB*)malloc(width*height * sizeof(RGB));
        if (!temp) {
            printf("Memory allocation failed\n");
            exit(1);
        }
    
        memcpy(temp, image, width*height * sizeof(RGB));
    
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                int flag = 0;
                for (k = -1; k <= 1; k++) {
                    for (l = -1; l <= 1; l++) {
                        m = i + k;
                        n = j + l;
                        if (m >= 0 && m < height && n >= 0 && n < width) {
                            if (temp[width*m + n].red == 0) {
                                int diff = abs(k) + abs(l);
                                if (diff == 1 || diff == 2) {
                                    flag = 1;
                                    break;
                                }
                            }
                        }
                    }
                    if (flag) {
                        break;
                    }
                }
                if (flag) {
                    image[width*i + j].red = 0;
                    image[width*i + j].green = 0;
                    image[width*i + j].blue = 0;
                }
                else {
                    image[width*i + j].red = 255;
                    image[width*i + j].green = 255;
                    image[width*i + j].blue = 255;
                }
            }
        }
    
        free(temp);
    }
    
    int main() {
        RGB* image;
        int width, height;
    
        readBmp("/Users/dezhiwoxing/Desktop/3.bmp", &image, &width, &height);
    
        // Image processing
        gray(image, width, height);
        binarize(image, width, height);
        dilate(image, width, height);
        erode(image, width, height);
        edgeDetection(image, width, height);
    
        saveBmp("/Users/dezhiwoxing/Desktop/result.bmp", image, width, height);
    
        free(image);
    
        return 0;
    }
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(7条)

报告相同问题?

问题事件

  • 系统已结题 6月25日
  • 已采纳回答 6月17日
  • 修改了问题 6月16日
  • 创建了问题 6月16日