我正在尝试在 OpenCV 中实现一种算法,以显示手掌静脉图案的细节。我以我在 Internet 上找到的名为“A Contactless Biometric System Using Palm Print and Palm Vein Features”的论文为基础。我感兴趣的部分是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;
}
所以这里遵循论文的主要步骤。对于某些部分,我从找到的代码中获得灵感。这是我发现的第一个处理的情况 here .同样对于高通滤波器(拉普拉斯算子),我从 OpenCV 2 Computer Vision Application Programming Cookbook 中给出的代码中获得启发。
最后,我做了一些小的改进,允许修改背景的亮度和静脉的暗度(参见定义 BRIGHT 和 DARK)。我还决定模糊一点蒙版以获得更“自然”的增强效果。
这里是结果(来源/论文结果/我的结果):
关于opencv - 使用 OpenCV 增强手掌静脉,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17195325/