亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 python 即 opencv 檢測裁剪面部的運動模糊

使用 python 即 opencv 檢測裁剪面部的運動模糊

幕布斯6054654 2022-01-11 16:48:03
我正在使用 haarcascade 檢測面部并使用 OpenCV 使用網絡攝像頭跟蹤它們。我需要保存每張被跟蹤的臉。但問題是人們何時移動。在這種情況下,臉部會變得模糊。我嘗試使用以下代碼使用 opencv 的 dnn 人臉檢測器和 Laplacian 來緩解這個問題:blob = cv2.dnn.blobFromImage(cropped_face, 1.0, (300, 300), (104.0, 177.0, 123.0))net.setInput(blob)detections = net.forward()confidence = detections[0, 0, 0, 2]blur = cv2.Laplacian(cropped_face, cv2.CV_64F).var()if confidence >= confidence_threshold and blur >= blur_threshold:    cv2.imwrite('less_blurry_image', cropped_face)在這里,如果由于運動而不是模糊,我嘗試將保存的臉限制setting blur_threshold為 500 和confidence_threshold0.98(即 98%)。但問題是如果我更換相機,我必須再次手動更改閾值。在大多數情況下,設置閾值會忽略大多數人臉。此外,由于與模糊的面部相比,背景總是清晰的,因此很難檢測到。所以我的問題是如何檢測面部的這種運動模糊。我知道我可以訓練一個用于面部運動模糊檢測的 ML 模型。但這將需要大量處理資源來完成一項小任務。此外,如果我走這條路,我將需要大量帶注釋的數據進行訓練。這對我這樣的學生來說并不容易。因此,我嘗試使用 OpenCV 來檢測這一點,與使用 ML 模型進行檢測相比,這將占用更少的資源。有沒有什么資源密集型解決方案可以解決這個問題?
查看完整描述

2 回答

?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

您可能可以使用傅立葉變換 (FFT) 或離散余弦變換 (DCT) 來確定您的面部有多模糊。圖像中的模糊導致高頻消失,只剩下低頻。

所以你會拍一張你的臉,把它補零到一個適合FFT或DCT的大小,然后看看你在更高頻率下有多少光譜功率。

您可能不需要 FFT - DCT 就足夠了。DCT 的優點是它產生實值結果(沒有虛部)。性能方面,FFT 和 DCT 對于 2 的冪的大小以及只有因子 2、3 和 5 的大小非??欤ūM管如果你也有 3 和 5,它會慢一點)。


查看完整回答
反對 回復 2022-01-11
?
PIPIONE

TA貢獻1829條經驗 獲得超9個贊

正如@PlinyTheElder 所提到的,DCT 信息可以為您提供運動模糊。我從下面的repo中附上了代碼片段:


代碼在里面C,我不確定是否有 python 綁定libjpeg。否則,您需要創建一個。


/* Fast blur detection using JPEG DCT coefficients

 *

 * Based on "Blur Determination in the Compressed Domain Using DCT

 * Information" by Xavier Marichal, Wei-Ying Ma, and Hong-Jiang Zhang.

 *

 * Tweak MIN_DCT_VALUE and MAX_HISTOGRAM_VALUE to adjust

 * effectiveness.  I reduced these values from those given in the

 * paper because I find the original to be less effective on large

 * JPEGs.

 *

 * Copyright 2010 Julian Squires <[email protected]>

 */


#include <string.h>

#include <stdlib.h>

#include <stdio.h>

#include <jpeglib.h>


static int min_dct_value = 1;   /* -d= */

static float max_histogram_value = 0.005; /* -h= */


static float weights[] = {  /* diagonal weighting */

    8,7,6,5,4,3,2,1,

    1,8,7,6,5,4,3,2,

    2,1,8,7,6,5,4,3,

    3,2,1,8,7,6,5,4,

    4,3,2,1,8,7,6,5,

    5,4,3,2,1,8,7,6,

    6,5,4,3,2,1,8,7,

    7,6,5,4,3,2,1,8

};

static float total_weight = 344;


static inline void update_histogram(JCOEF *block, int *histogram)

{

    for(int k = 0; k < DCTSIZE2; k++, block++)

        if(abs(*block) > min_dct_value) histogram[k]++;

}


static float compute_blur(int *histogram)

{

    float blur = 0.0;

    for(int k = 0; k < DCTSIZE2; k++)

        if(histogram[k] < max_histogram_value*histogram[0])

            blur += weights[k];

    blur /= total_weight;

    return blur;

}



static int operate_on_image(char *path)

{

        struct jpeg_error_mgr jerr;

    struct jpeg_decompress_struct cinfo;

    jvirt_barray_ptr *coeffp;

    JBLOCKARRAY cs;

    FILE *in;

    int histogram[DCTSIZE2] = {0};


        cinfo.err = jpeg_std_error(&jerr);

        jpeg_create_decompress(&cinfo);

    if((in = fopen(path, "rb")) == NULL) {

        fprintf(stderr, "%s: Couldn't open.\n", path);

        jpeg_destroy_decompress(&cinfo);

        return 0;

    }

    jpeg_stdio_src(&cinfo, in);

    jpeg_read_header(&cinfo, TRUE);

    // XXX might be a little faster if we ask for grayscale

    coeffp = jpeg_read_coefficients(&cinfo);


    /* Note: only looking at the luma; assuming it's the first component. */

    for(int i = 0; i < cinfo.comp_info[0].height_in_blocks; i++) {

        cs = cinfo.mem->access_virt_barray((j_common_ptr)&cinfo, coeffp[0], i, 1, FALSE);

        for(int j = 0; j < cinfo.comp_info[0].width_in_blocks; j++)

            update_histogram(cs[0][j], histogram);

    }


    printf("%f\n", compute_blur(histogram));

    // output metadata XXX should be in IPTC etc


    // XXX also need to destroy coeffp?

    jpeg_destroy_decompress(&cinfo);

    return 0;

}


int main(int argc, char **argv)

{

    int status, i;


    for(status = 0, i = 1; i < argc; i++) {

        if(argv[i][0] == '-') {

            if(argv[i][1] == 'd')

                sscanf(argv[i], "-d=%d", &min_dct_value);

            else if(argv[i][1] == 'h')

                sscanf(argv[i], "-h=%f", &max_histogram_value);

            continue;

        }

        status |= operate_on_image(argv[i]);

    }


    return status;

}

編譯代碼:


gcc -std=c99 blur_detection.c -l jpeg -o blur-detection

運行代碼:


./blur-detection <image path>


查看完整回答
反對 回復 2022-01-11
  • 2 回答
  • 0 關注
  • 283 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號