【发布时间】:2015-03-27 07:56:26
【问题描述】:
我正在尝试实现Anil Jain改进指纹图像的方法。作为初学者,我在提取方向图像时遇到了一些困难,我严格遵循该论文第 2.4 节中描述的步骤。
所以,这是输入图像:
这是在使用与该论文中完全相同的方法进行归一化之后:
我期待看到这样的东西(来自互联网的一个例子):
但是,这是我显示获得的方向矩阵的结果:
显然这是错误的,它还为原始输入图像中的那些零点提供了非零值。
这是我写的代码:
cv::Mat orientation(cv::Mat inputImage)
{
cv::Mat orientationMat = cv::Mat::zeros(inputImage.size(), CV_8UC1);
// compute gradients at each pixel
cv::Mat grad_x, grad_y;
cv::Sobel(inputImage, grad_x, CV_16SC1, 1, 0, 3, 1, 0, cv::BORDER_DEFAULT);
cv::Sobel(inputImage, grad_y, CV_16SC1, 0, 1, 3, 1, 0, cv::BORDER_DEFAULT);
cv::Mat Vx, Vy, theta, lowPassX, lowPassY;
cv::Mat lowPassX2, lowPassY2;
Vx = cv::Mat::zeros(inputImage.size(), inputImage.type());
Vx.copyTo(Vy);
Vx.copyTo(theta);
Vx.copyTo(lowPassX);
Vx.copyTo(lowPassY);
Vx.copyTo(lowPassX2);
Vx.copyTo(lowPassY2);
// estimate the local orientation of each block
int blockSize = 16;
for(int i = blockSize/2; i < inputImage.rows - blockSize/2; i+=blockSize)
{
for(int j = blockSize / 2; j < inputImage.cols - blockSize/2; j+= blockSize)
{
float sum1 = 0.0;
float sum2 = 0.0;
for ( int u = i - blockSize/2; u < i + blockSize/2; u++)
{
for( int v = j - blockSize/2; v < j+blockSize/2; v++)
{
sum1 += grad_x.at<float>(u,v) * grad_y.at<float>(u,v);
sum2 += (grad_x.at<float>(u,v)*grad_x.at<float>(u,v)) * (grad_y.at<float>(u,v)*grad_y.at<float>(u,v));
}
}
Vx.at<float>(i,j) = sum1;
Vy.at<float>(i,j) = sum2;
double calc = 0.0;
if(sum1 != 0 && sum2 != 0)
{
calc = 0.5 * atan(Vy.at<float>(i,j) / Vx.at<float>(i,j));
}
theta.at<float>(i,j) = calc;
// Perform low-pass filtering
float angle = 2 * calc;
lowPassX.at<float>(i,j) = cos(angle * pi / 180);
lowPassY.at<float>(i,j) = sin(angle * pi / 180);
float sum3 = 0.0;
float sum4 = 0.0;
for(int u = -lowPassSize / 2; u < lowPassSize / 2; u++)
{
for(int v = -lowPassSize / 2; v < lowPassSize / 2; v++)
{
sum3 += inputImage.at<float>(u,v) * lowPassX.at<float>(i - u*lowPassSize, j - v * lowPassSize);
sum4 += inputImage.at<float>(u, v) * lowPassY.at<float>(i - u*lowPassSize, j - v * lowPassSize);
}
}
lowPassX2.at<float>(i,j) = sum3;
lowPassY2.at<float>(i,j) = sum4;
float calc2 = 0.0;
if(sum3 != 0 && sum4 != 0)
{
calc2 = 0.5 * atan(lowPassY2.at<float>(i, j) / lowPassX2.at<float>(i, j)) * 180 / pi;
}
orientationMat.at<float>(i,j) = calc2;
}
}
return orientationMat;
}
我已经在网上搜索了很多,但几乎所有这些都在 Matlab 中。使用 OpenCV 的人很少,但他们也没有帮助我。我真诚地希望有人可以通过我的代码并指出任何错误来提供帮助。先感谢您。
更新
这是我根据论文所遵循的步骤:
- 获取归一化图像 G。
- 将 G 分成大小为 wxw (16x16) 的块。
- 计算每个像素 (i,j) 处的 x 和 y 梯度。
使用以下等式估计以像素 (i,j) 为中心的每个块的局部方向:
执行低通滤波以去除噪声。为此,将方向图像转换为定义为的连续向量场:
其中W是一个二维低通滤波器,w(phi) x w(phi)是它的大小,等于5。
- 最后,计算 (i,j) 处的局部脊方向:
更新2
这是在 Sobel 操作中将 mat 类型更改为 CV_16SC1 后,orientationMat 的输出,如 Micka 建议的:
【问题讨论】:
-
方向矩阵为您提供给定点的方向角度。现在您不应该绘制方向矩阵,而是在图像上为每个给定点绘制具有该角度方向的线...
-
没有看你的算法tbh...你能添加一些伪代码和相应的代码cmet来解释你想要做什么吗?
-
orientationMat 是在某处创建的吗?据我所知,它应该是一个空的 Mat 并且在设置元素值时应该在函数中出现运行时错误...
-
在您提供的代码中声明但不初始化orientationMat?!?所以orientationMat.at
(i,j) = calc2;应该给出错误...请提供该函数的完整代码! -
您的代码中存在一个问题:您的 sobel 结果是 8UC1,它不能处理负面结果,应该改为 16SC1
标签: image opencv image-processing fingerprint image-enhancement