OpenCV增强手掌静脉

OpenCV增强手掌静脉,opencv,filtering,biometrics,image-enhancement,Opencv,Filtering,Biometrics,Image Enhancement,我试图在OpenCV中实现一个算法,以显示手掌静脉模式的细节。我是根据我在网上找到的一篇名为“”的论文写的。我感兴趣的部分是章节3.2预处理。所涉及的步骤如图所示 我想用OpenCV来实现,但到目前为止,我一直很努力。特别是他们在低通滤波器的响应上使用拉普拉斯滤波器来隔离主静脉,但无论我尝试什么参数,我的结果都非常嘈杂 任何帮助都将不胜感激 好了,我终于自己想出了办法。这是我的密码: #include <opencv2/core/core.hpp> #include <open

我试图在OpenCV中实现一个算法,以显示手掌静脉模式的细节。我是根据我在网上找到的一篇名为“”的论文写的。我感兴趣的部分是章节3.2预处理。所涉及的步骤如图所示

我想用OpenCV来实现,但到目前为止,我一直很努力。特别是他们在低通滤波器的响应上使用拉普拉斯滤波器来隔离主静脉,但无论我尝试什么参数,我的结果都非常嘈杂


任何帮助都将不胜感激

好了,我终于自己想出了办法。这是我的密码:

#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://stackoverflow.com/a/14874992/2501769
    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;
}
#包括
#包括
#包括
#定义阈值150
#定义亮度0.7
#定义暗0.2
使用名称空间std;
使用名称空间cv;
int main()
{
//以灰度模式读取源图像
Mat img=imread(“roi.png”,CV\u LOAD\u IMAGE\u灰度);
//从应用???算法https://stackoverflow.com/a/14874992/2501769
垫增强,浮灰,模糊,数值,密度;
img.convertTo(浮动灰色,CV_32F,1.0/255.0);
cv::高斯模糊(浮动灰,模糊,大小(0,0),10);
num=浮动\灰色-模糊;
cv::高斯模糊(num.mul(num),模糊,大小(0,0),20);
cv::功率(模糊,0.5,密度);
增强=个/den;
cv::标准化(增强,增强,0.025.0,NORM_MINMAX,-1);
增强型.convertTo(增强型,CV_8UC1);
//低通滤波器
马特高斯;
cv::高斯模糊(增强,高斯,大小(0,0),3);
//计算低通图像的高通滤波
拉普拉斯垫;
拉普拉斯(高斯,拉普拉斯,CV_32F,19);
双圈最小值,圈最大值;
minMaxLoc(拉普拉斯、拉普明和拉普马克斯);
双刻度=127/最大值(-lapmin,lapmax);
拉普拉斯变换器(拉普拉斯,CV_8U,刻度,128);
//使用经验值150进行阈值化以创建静脉遮罩
垫罩;
cv::threshold(拉普拉斯、蒙版、阈值、255、cv_THRESH_二进制);
//使用开放式形态学操作清理面罩
形态学(遮罩,遮罩,cv::形态开放,
getStructuringElement(cv::变形椭圆,cv::大小(5,5));
//使用闭合形态学操作连接相邻区域
垫子连接;
morphologyEx(遮罩,遮罩,cv::变形关闭,
getStructuringElement(cv::变形椭圆,cv::大小(11,11));
//模糊遮罩以获得更平滑的增强效果
cv::GaussianBlur(掩模,掩模,尺寸(15,15),0);
//模糊一点的图像,以及消除噪音
cv::高斯蓝(增强,增强,大小(3,3),0);
//这个面具是用来放大静脉的
Mat结果(增强);
ushort新像素;
双系数;

对于(int i=0;i您可以发布用于预处理的代码吗?如果我理解正确,为了找到边,您应该在拉普拉斯算子的输出中寻找零交叉点(尽管论文实际上似乎做了一些不同的事情).BTW,看看我的手掌,区分主脊线和纹理的主要特征是颜色,所以这可能是一个更好的尝试。你能发布你的结果图像吗?你考虑过使用LBP过滤器吗?这将生成振幅不变的图像(即,只有图案,而不是对比度/亮度)。鉴于您只需要veincode编码步骤的相位信息,这可能是一个“更干净”的预处理步骤。