基于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;
}

测试

测试图像

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

测试结果

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

参考

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Digital2Slave

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值