OpenCV实现的手掌静脉增强技术

3
我正在尝试在OpenCV中实现一种算法,以突出手掌静脉图案的细节。我参考了一篇名为“使用手掌印和手掌静脉特征的非接触生物识别系统”的论文,该论文是我在互联网上找到的。我感兴趣的部分是第3.2预处理章节。其中涉及的步骤在那里显示。
我想使用OpenCV进行实现,但到目前为止我卡住了。特别是他们将拉普拉斯滤波器用于低通滤波器的响应上,以隔离主要静脉,但无论我尝试什么参数,我的结果都非常嘈杂!
任何帮助都将不胜感激!

你能发一下你预处理的代码吗?如果我理解正确,要找到边缘,你应该在拉普拉斯算子的输出中寻找零交叉点(尽管论文似乎在做一些不同的事情)。顺便说一句,看着我的手掌,区分主脊线和静脉与其他所有东西的主要特征是颜色,所以这可能是一个更好的尝试。 - Bull
1个回答

7

好的,最后我自己想出了如何做。这是我的代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#define THRESHOLD 150
#define BRIGHT 0.7
#define DARK 0.2

using namespace std;
using namespace cv;

int main()
{

    // Read source image in grayscale mode
    Mat img = imread("roi.png", CV_LOAD_IMAGE_GRAYSCALE);

    // Apply ??? algorithm from https://dev59.com/U27Xa4cB1Zd3GeqPp3XN#14874992
    Mat enhanced, float_gray, blur, num, den;
    img.convertTo(float_gray, CV_32F, 1.0/255.0);
    cv::GaussianBlur(float_gray, blur, Size(0,0), 10);
    num = float_gray - blur;
    cv::GaussianBlur(num.mul(num), blur, Size(0,0), 20);
    cv::pow(blur, 0.5, den);
    enhanced = num / den;
    cv::normalize(enhanced, enhanced, 0.0, 255.0, NORM_MINMAX, -1);
    enhanced.convertTo(enhanced, CV_8UC1);

    // Low-pass filter
    Mat gaussian;
    cv::GaussianBlur(enhanced, gaussian, Size(0,0), 3);

    // High-pass filter on computed low-pass image
    Mat laplace;
    Laplacian(gaussian, laplace, CV_32F, 19);
    double lapmin, lapmax;
    minMaxLoc(laplace, &lapmin, &lapmax);
    double scale = 127/ max(-lapmin, lapmax);
    laplace.convertTo(laplace, CV_8U, scale, 128);

    // Thresholding using empirical value of 150 to create a vein mask
    Mat mask;
    cv::threshold(laplace, mask, THRESHOLD, 255, CV_THRESH_BINARY);

    // Clean-up the mask using open morphological operation
    morphologyEx(mask,mask,cv::MORPH_OPEN,
        getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5)));

    // Connect the neighboring areas using close morphological operation
    Mat connected;
    morphologyEx(mask,mask,cv::MORPH_CLOSE,
        getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(11,11)));

    // Blurry the mask for a smoother enhancement
    cv::GaussianBlur(mask, mask, Size(15,15), 0);

    // Blurry a little bit the image as well to remove noise
    cv::GaussianBlur(enhanced, enhanced, Size(3,3), 0);

    // The mask is used to amplify the veins
    Mat result(enhanced);
    ushort new_pixel;
    double coeff;
    for(int i=0;i<mask.rows;i++){
        for(int j=0;j<mask.cols;j++){
            coeff = (1.0-(mask.at<uchar>(i,j)/255.0))*BRIGHT + (1-DARK);
            new_pixel = coeff * enhanced.at<uchar>(i,j);
            result.at<uchar>(i,j) = (new_pixel>255) ? 255 : new_pixel;
        }
    }

    // Show results
    imshow("frame", img);
    waitKey();

    imshow("frame", result);
    waitKey();

    return 0;
}

所以该论文的主要步骤在此处遵循。对于一些部分,我受到了我发现的代码的启发。这是我找到的第一个处理应用的情况,链接在这里。对于高通滤波器(拉普拉斯)我也受到了给定的OpenCV 2计算机视觉应用程序编程食谱中的代码的启发。

最后,我通过允许修改背景亮度和静脉暗度(见定义BRIGHT和DARK)做了一些小改进。我还决定模糊一下掩模,以更自然地增强图像。


这里是结果(源/论文结果/我的结果):

源图像 论文结果 我的结果


你能发布你的生成图像吗? - joshim5
1
你考虑过使用LBP滤波器吗?这将产生一个幅度不变的图像(即仅模式,而非对比度/亮度)。考虑到你只需要静脉编码步骤的相位信息,这可能是一个更“清洁”的预处理步骤。 - cjm2671

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接