- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我尝试按照这种方法绘制方位图http://answers.opencv.org/question/9493/fingerprint-orientation-map-through-gradient/
我在 480x320 图像上使用了 5x5 的 block 大小。我得到的梯度是从 0-270 度。并且有不断重复的常数值,如 44.7623 和 224.762。我想知道我的梯度是否有误。
之后,我将所有渐变添加到 5x5 block 中,并将它们除以 25(平均),就像链接所说的那样。我将度数分成 45 度间隔的 8 个部分并绘制出来。但它看起来与我的原始图像完全不同。谁能告诉我怎么了?我只想检测图像的核心(圆形)特征。
我的原始图像是 _____________________________________________________________ 但我的方向图是这样的:
这就是我正在做的
怎么了? =(
我从这个方法得到了梯度:
/// Gradient X
cv::Sobel(original_Mat, grad_x, CV_32FC1, 1, 0, 3);
/// Gradient Y
cv::Sobel(original_Mat, grad_y, CV_32FC1, 0, 1, 3);
Mat orientation = Mat(grad_x.rows, grad_y.cols, CV_32F);
for(int i = 0; i < grad_x.rows; i++){
for(int j = 0; j < grad_x.cols; j++){
// Retrieve a single value
float valueX = grad_x.at<float>(i,j);
float valueY = grad_x.at<float>(i,j);
// Calculate the corresponding single direction, done by applying the arctangens function
float result = fastAtan2(valueX,valueY);
// Store in orientation matrix element
orientation.at<float>(i,j) = result;
}
}
这是完整的代码。
int main()
{
cv::Mat original_Mat=cv::imread("Source.bmp", 1);
cv::Mat grad = cv::Mat::zeros(original_Mat.size(),CV_64F);
/// Generate grad_x and grad_y
cv::Mat grad_x = cv::Mat::zeros(original_Mat.size(), CV_64F);
cv::Mat grad_y = cv::Mat::zeros(original_Mat.size(), CV_64F);
cv::Mat grad_angle = cv::Mat::zeros(original_Mat.size(), CV_64F);
/// Gradient X
cv::Sobel(original_Mat, grad_x, CV_32FC1, 1, 0, 3);
/// Gradient Y
cv::Sobel(original_Mat, grad_y, CV_32FC1, 0, 1, 3);
Mat orientation = Mat(grad_x.rows, grad_y.cols, CV_32F); //to store the gradients
Mat img=Mat(grad_x.rows, grad_y.cols, CV_32F);//to draw out the map
img = cv::Scalar(255,255,255);//all white
// Calculate orientations of gradients --> in degrees
// Loop over all matrix values and calculate the accompanied orientation
for(int i = 0; i < grad_x.rows; i++){
for(int j = 0; j < grad_x.cols; j++){
// Retrieve a single value
float valueX = grad_x.at<float>(i,j);
float valueY = grad_x.at<float>(i,j);
// Calculate the corresponding single direction, done by applying the arctangens function
float result = fastAtan2(valueX,valueY);
// Store in orientation matrix element
orientation.at<float>(i,j) = result;
}
}
int i=0,j=0;
int x1=0,x2=0;
float results;
for(int l=0;l<96;l++) //to loop all the rows
{
int x1=(5+(l*5)); // to get 5x5 block sizes
for(int k=0;k<64;k++)//to loop all the columns
{
int x2=(5+(k*5)); // to get 5x5 block sizes
results=0;
//to get the total of 5x5 gradient values
for(i=(x1-5); i < x1; i++){
for(j=(x2-5); j < x2; j++){
results=results+orientation.at<float>(i,j);
orientation.at<float>(i,j)=0;
}
}
results=results/25; //averaging the 5x5 block gradients
orientation.at<float>((x1-3),(x2-3))=results; //to store the results in the center of the 5x5 block
}
}
results=0;
//this loop is to draw out the orientation map
for(int i=0;i<480;i++)
{
for(int j=0;j<320;j++)
{
results=orientation.at<float>(i,j);
if ((results<=22.5)&&(results>0)){
results=0;
img.at<int>(i,j)=255;
img.at<int>(i,j+1)=255;
img.at<int>(i,j+2)=255;
}
else if((results>22.5)&&(results<=67.5)){
results=45;
img.at<int>(i,j)=255;
img.at<int>(i-1,j+1)=255;
img.at<int>(i-2,j+2)=255;
}
else if((results>67.5)&&(results<=112.5)){
results=90;
img.at<int>(i,j)=255;
img.at<int>(i-1,j)=255;
img.at<int>(i-2,j)=255;
}
else if((results>112.5)&&(results<=157.5)){
results=135;
img.at<int>(i,j)=255;
img.at<int>(i-1,j-1)=255;
img.at<int>(i-2,j-2)=255;
}
else if((results>157.5)&&(results<=202.5)){
results=180;
img.at<int>(i,j)=255;
img.at<int>(i,j-1)=255;
img.at<int>(i,j-2)=255;
}
else if((results>202.5)&&(results<=247.5)){
results=225;
img.at<int>(i,j)=255;
img.at<int>(i+1,j-1)=255;
img.at<int>(i+2,j-2)=255;
endx=x2-5;
endy=x1-1;
}
else if((results>247.5)&&(results<=292.5)){
results=270;
img.at<int>(i,j)=255;
img.at<int>(i+1,j)=255;
img.at<int>(i+2,j)=255;
}
else if((results>292.5)&&(results<=337.5)){
results=315;
img.at<int>(i,j)=255;
img.at<int>(i+1,j+1)=255;
img.at<int>(i+2,j+2)=255;
}
else
{
results=0;
}
orientation.at<float>(i,j)=results;
}
}
最佳答案
这是我的结果:对于图像:
我得到了结果:
代码:
#include <stdio.h>
#include <stdarg.h>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
namedWindow("source");
namedWindow("result");
namedWindow("ang");
Mat img=imread("D:\\ImagesForTest\\binarized_image.png",0);
cv::threshold(img,img,128,255,cv::THRESH_BINARY);
Mat thinned;
thinned=img.clone(); // Just clone the input
//Thinning(img,thinned); // Not actually needed
cv::GaussianBlur(thinned,thinned,Size(3,3),1.0);
Mat gx,gy,ang,mag;
cv::Sobel(thinned,gx,CV_32FC1,1,0);
cv::Sobel(thinned,gy,CV_32FC1,0,1);
cv::phase(gx,gy,ang,false);
cv::magnitude(gx,gy,mag);
cv::normalize(mag,mag,0,1,cv::NORM_MINMAX);
Mat angRes=Mat::zeros(img.rows*3,img.cols*3,CV_8UC1);
for (int i=0;i< img.rows;i+=2)
{
for (int j=0;j< img.cols;j+=2)
{
int x=j*3;
int y=i*3;
float r=5;
float m=r*(mag.at<float>(i,j));
float dx=m*r*cos(ang.at<float>(i,j));
float dy=m*r*sin(ang.at<float>(i,j));
cv::line(angRes,cv::Point(x,y),cv::Point(x+dx,y+dy),Scalar::all(255),1,CV_AA);
}
}
imshow("ang",angRes);
imshow("source",img);
imshow("result",thinned);
cv::waitKey(0);
}
另一种变体(加权 block 平均值):
#include <stdio.h>
#include <stdarg.h>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
float GetWeightedAngle(Mat& mag,Mat& ang)
{
float res=0;
float n=0;
for (int i=0;i< mag.rows;++i)
{
for (int j=0;j< mag.cols;++j)
{
res+=ang.at<float>(i,j)*mag.at<float>(i,j);
n+=mag.at<float>(i,j);
}
}
res/=n;
return res;
}
int main(int argc, char* argv[])
{
namedWindow("source");
namedWindow("ang");
Mat img=imread("D:\\ImagesForTest\\binarized_image.png",0);
cv::threshold(img,img,128,255,cv::THRESH_BINARY);
Mat thinned;
thinned=img.clone();
//Thinning(img,thinned);
//cv::GaussianBlur(thinned,thinned,Size(3,3),1.0);
Mat gx,gy,ang,mag;
cv::Sobel(thinned,gx,CV_32FC1,1,0,7);
cv::Sobel(thinned,gy,CV_32FC1,0,1,7);
cv::phase(gx,gy,ang,false);
cv::magnitude(gx,gy,mag);
cv::normalize(mag,mag,0,1,cv::NORM_MINMAX);
Mat angRes=Mat::zeros(img.rows,img.cols,CV_8UC1);
int blockSize=img.cols/15-1;
float r=blockSize;
for (int i=0;i< img.rows-blockSize;i+= blockSize)
{
for (int j=0;j< img.cols-blockSize;j+= blockSize)
{
float a=GetWeightedAngle(mag(Rect(j,i,blockSize,blockSize)),ang(Rect(j,i,blockSize,blockSize)));
float dx=r*cos(a);
float dy=r*sin(a);
int x=j;
int y=i;
cv::line(angRes,cv::Point(x,y),cv::Point(x+dx,y+dy),Scalar::all(255),1,CV_AA);
}
}
imshow("ang",angRes);
imshow("source",img);
cv::waitKey(0);
}
它给出了结果图像:
关于c++ - 使用 sobel 的奇怪方向图。怎么了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22953666/
我想填充 3D 等高线图 (contour3(X,Y,Z)),就像 2D 等高线填充图 (contourf(X,Y,Z))。但我无法弄清楚如何实现这一目标。 contour3 和 surf 的组合不是
我有一个 c3.js 折线图,表示 2 个值的演变。我需要折线图的工具提示是饼图(工具提示 = 另一个 c3.js 图形)。 这是我成功的: http://jsfiddle.net/owhxgaqm/
我有具有结构的 Pandas 数据框: A B 0 1 1 1 2 1 2 3 4 3 3 7 4 6 8 如何生成 Seaborn Violin 图,每列作为其自己的单独
我正在使用 D3DXSPRITE 方法将我的 map 图 block 绘制到屏幕上,我刚刚添加了一个缩放功能,当您按住向上箭头时会放大,但注意到您现在可以看到图 block 之间的间隙,这是一些屏幕截
今天我们开始学习目前学习到的最难最复杂的数据结构图。 简单回顾一下之前学习的数据结构,数组、单链表、队列等线性表中数据元素是一对一关系,而树结构中数据元素是一对多关系,而图结构中数据元素则是多对
1、系统环境如下图: 2、为该系统添加一块新的虚拟硬盘,添加后需重启虚拟机,否则系统不识别;如下图,/dev/sdc 是新添加的硬盘; 3、fdisk /dev/sdc为新硬盘创建分区:
1、nagios简介 nagios是一款开源的电脑系统和网络监视工具,能有效监控windows、linux和unix的主机状态,交换机路由器等网络设置,打印机等。在系统或服务状态异常时发
越来越多人开始习惯用手机上网,浏览网页、查看邮件···移动化已经成为互联网发展必然趋势,包括facebook在内的很多互联网公司都将移动广告作为下一个淘金地
1.图片处理 1.圆角图片 复制代码 代码如下: /** * 转换成圆角 * &n
Microsoft SQL Server Management Studio是SQL SERVER的客户端工具,相信大家都知道。我不知道大伙使用导入数据的情况怎么样,反正我最近是遇到过。主要是因为没
debian6系统: 首先先安装mysql吧: 打开终端(root)用户登入 apt-get purge mysql-server-5.5 安装完成后: 默认情况下Mysql只允许本地登录
fedora16英文环境下支持中文输入法的方法 fedora16英文环境下支持FCITX的中文输入法: $ im-chooser 就会出现选择界面,选择第二个就行了。
Net预编译命令 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -? 显示说明 我们需要选择的命令为&n
有的时候电脑出现一些故障有的时候通过将其修改bios设置的方法来解决故障,那么在bios上设置能不能将电脑恢复出厂设置呢?其实也是可以的。方法也很简单的,只要会进入电脑的bios懂的上面英文的意思就
笔者曾介绍过Deepin 将对龙芯进行全面支持,打造最优美龙芯电脑桌面。现在Deepin团队移植工作取得了突破性的成果,Deepin桌面已经在龙芯3A和龙芯3B电脑上成功运行起来了。 以下为龙芯3
在安装一些软件之后,我们的电脑总是会发生一点小变化,不是桌面上多了几个网址图标,就是IE浏览器的默认主页被篡改成乱七八糟的网址。最可气的是,在IE设置中将默认主页改回来后,下次启动Win7后又变了回
“注册表编辑器怎么打开”虽说不是很难的问题,但是对于对电脑常识不是很擅长的网民来说,当电脑出现问题或需要更改设置时,着实还是件头疼的问题。因为需要打开注册表进行操作解决。那么如何打开注册表编辑器呢?
这篇文章重点介绍10个重要的WordPress安全插件和技巧,用来保护WordPress网站或者博客。 1. WP Security 人工帮助你修复被黑客入侵的网站,只要按照他们网站上的联系电话
其实运用object和javascript调用外部文件,也能实现不同栏目调用不同友情链接,即相当于调用不同栏目友情链接文件, {dede:field.typeid/}来获取当前栏目的ID。
我有一个复值矩阵。 如果我发出命令: plot(myMatrix) 然后它在图形设备上显示一种散点图,X 轴标记为 Re(myMatrix),Y 轴标记为 Im(myMatrix)。这显示了我正在寻找
我是一名优秀的程序员,十分优秀!