基於OpenCV的圖像模糊與否檢測

本文用以記錄,圖像模糊與否的一種檢測方法,該方法主要採用圖像的拉普拉斯卷積操作。

源碼

blur_detection.h

#pragma once
#ifndef BLUR_DETECTION_H
#define BLUR_DETECTION_H

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"

double variance_of_laplacian(const IplImage* img);

void show_image(const char* winname, const IplImage* img, float waittime);

void draw_and_show_image(const IplImage* img, char* content, float waittime);

void delete_duplicates_image(const char* imgpath);

/*C substring function: It returns a pointer to the substring */
char *substring(char *string, int position, int length);

bool isImageFile(const char* img_name);

#endif //!< BLUR_DETECTION_H

blur_detection.cpp

#include "blur_detection.h"

void show_image(const char* winname, const IplImage* img, float waittime)
{
    cvNamedWindow(winname, CV_WINDOW_AUTOSIZE);
    cvShowImage(winname, img);
    int timedelay = (int)(waittime * 1000);
    cvWaitKey(timedelay);
    cvDestroyWindow(winname);
}

void draw_and_show_image(const IplImage* img, char* content, float waittime)
{
    IplImage* draw = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
    if (img->nChannels == 1)
    {
        cvCvtColor(img, draw, CV_GRAY2BGR);
    }
    else
    {
        cvCopy(img, draw, NULL);
    }

    CvPoint org;
    org.x = 10;
    org.y = 30;
    CvFont font;
    cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0, 0, 2, 8);
    cvPutText(draw, content, org, &font, CV_RGB(255, 255, 0));
    show_image("label", draw, waittime);
    cvReleaseImage(&draw);
}

double variance_of_laplacian(const IplImage* img)
{
    if (img == NULL)
    {
        return 0.0;
    }
    const int imgrows = img->height;
    const int imgcols = img->width;
    IplImage* gray = cvCreateImage(cvSize(imgcols, imgrows), IPL_DEPTH_8U, 1);
    if (img->nChannels == 3)
    {
        cvCvtColor(img, gray, CV_BGR2GRAY);
    }
    else if (img->nChannels == 1)
    {
        cvCopy(img, gray, NULL);
    }
    else
    {
        cvCvtColor(img, gray, CV_BGRA2GRAY);
    }

    IplImage* lap = cvCreateImage(cvSize(imgcols, imgrows), IPL_DEPTH_64F, 1);
    cvLaplace(gray, lap, 3);
    cvReleaseImage(&gray);

    CvScalar lap_mean, lap_stddev;
    cvAvgSdv(lap, &lap_mean, &lap_stddev, NULL);
    cvReleaseImage(&lap);

    return lap_stddev.val[0];
}

void delete_duplicates_image(const char* imgpath)
{
    int status;
    status = remove(imgpath);
    if (status == 0)
    {
        printf("%s file deleted successfully.\n", imgpath);
    }
    else
    {
        printf("Unable to delete the file\n");
        perror("Error");
    }
}


char *substring(char *string, int position, int length)
{
    char *pointer = NULL;
    pointer = malloc(length + 1);
    if (pointer == NULL)
    {
        printf("Unable to allocate memory.\n");
        exit(1);
    }
    int c = 0;
    for (c = 0; c < length; c++)
    {
        *(pointer + c) = *(string + position - 1);
        string++;
    }
    *(pointer + c) = '\0';
    return pointer;
}

bool isImageFile(const char* img_name)
{
    // find last '.' of img_name
    int lastIdx = 0;
    int lenStr = strlen(img_name);
    int len = lenStr;
    while (--len)
    {
        char c = img_name[len];
        if (c == '.')
        {
            lastIdx = len;
            break;
        }
    }

    // substr
    char* imgpox = substring(img_name, lastIdx + 2, lenStr - lastIdx + 1);
    int r1 = strcmp(imgpox, "jpg");
    int r2 = strcmp(imgpox, "JPG");
    int r3 = strcmp(imgpox, "jpeg");
    int r4 = strcmp(imgpox, "JPEG");

    if (r1 == 0 || r2 == 0 || r3 == 0 || r4 == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

main.cpp

#include "blur_detection.h"
#include <dirent.h>
#include <locale.h>

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        printf("Usage:\n*.exe <image path>\n");
        return -1;
    }

    setlocale(LC_CTYPE, "");  // 處理中文命名的圖像名稱
    const char* img_path = argv[1];

    if (isImageFile(img_path))
    {
        // detect the blurness of image
        IplImage* img = cvLoadImage(img_path, 1);
        double stdv = variance_of_laplacian(img);
        char* rest = NULL;
        if (stdv <= 50)
        {
            rest = "blur ";
        }
        else
        {
            rest = "not blur ";
        }
        char buffer[10];
        snprintf(buffer, 10, "%.2f", stdv);
        char content[50];
        strcpy(content, rest);
        strcat(content, buffer);
        draw_and_show_image(img, content, 0);
        cvReleaseImage(&img);
    }
    return 0;
}

測試

測試圖像

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

測試結果

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章