从两幅图像的匹配点计算焦距f

从网络中找到两种计算焦距的方法
1。两幅图像的单应矩阵H计算焦距f(取自《全景图拼接》opencv代码)

//从两幅图像的单应矩阵H计算焦距f。
void focalsFromHomography(const Mat& H, double &f0, double &f1, bool &f0_ok, bool &f1_ok)
{
    CV_Assert(H.type() == CV_64F && H.size() == Size(3, 3));

    const double* h = H.ptr<double>();//h 是一个向量

    double d1, d2; // 分母
    double v1, v2; // 焦距平方值候选

    f1_ok = true;
    d1 = h[6] * h[7];
    d2 = (h[7] - h[6]) * (h[7] + h[6]);
    v1 = -(h[0] * h[1] + h[3] * h[4]) / d1;
    v2 = (h[0] * h[0] + h[3] * h[3] - h[1] * h[1] - h[4] * h[4]) / d2;
    if (v1 < v2) std::swap(v1, v2);
    if (v1 > 0 && v2 > 0) f1 = std::sqrt(std::abs(d1) > std::abs(d2) ? v1 : v2);
    else if (v1 > 0) f1 = std::sqrt(v1);
    else f1_ok = false;

    f0_ok = true;
    d1 = h[0] * h[3] + h[1] * h[4];
    d2 = h[0] * h[0] + h[1] * h[1] - h[3] * h[3] - h[4] * h[4];
    v1 = -h[2] * h[5] / d1;
    v2 = (h[5] * h[5] - h[2] * h[2]) / d2;
    if (v1 < v2) std::swap(v1, v2);
    if (v1 > 0 && v2 > 0) f0 = std::sqrt(std::abs(d1) > std::abs(d2) ? v1 : v2);
    else if (v1 > 0) f0 = std::sqrt(v1);
    else f0_ok = false;
}

用下面的测试

	//读入两个图
	Mat img1 = imread(name1);//
	Mat img2 = imread(name2);//

	//匹配
	vector<KeyPoint> kp1,kp2;
	vector<DMatch> matches;
	meMatch2(img1, img2,kp1,kp2,matches);


	//生成匹配点
	vector<Point2f> points1, points2;
	get_match_points (kp1, kp2, matches, points1, points2);

	//4对相对应的像点计算图像的单应 Homography
	Mat H = findHomography(points1, points2, 0);

	double f0; double f1; bool f0_ok; bool f1_ok;
	//从两幅图像的单应矩阵H计算焦距f。
	focalsFromHomography(H, f0, f1, f0_ok, f1_ok);
	if (f0_ok)
			std::cout <<"图1焦距:"<< f0 << '\n';
	if (f1_ok)
			std::cout <<"图2焦距:"<< f1 << '\n';

结果:


图1焦距:81.9963
图2焦距:992.465
只有图2计算得很算准确。


-=-=-=-=-=-=-=-=-=-----------------分隔线------------------------=-=-=-=-=-=-=-=-=


2。两图的匹配点计算焦距f(取自一个《极线校正工具包》matlab)

function [f] = compIntrinsic (ml,mr,width,height)
%计算一个焦距
%
%
% ml,mr 是图像中的对应点 
%
% width, height 是图像的尺寸(用于取得焦距和图像中心)
% 



options = optimset('Jacobian','off');

a0 = [0 0 0 0 0, 0];
[af,resnorm,residual,exitflag,output,lambda,jacobian] = lsqnonlin(@(x) costRectif(x,width,height,ml,mr), a0,...
    [-pi/2, -pi/2, -pi/2, -pi/2, -pi/2, -1.5], [pi/2, pi/2, pi/2, pi/2, pi/2, 1.5],options);

counter = 0;
while af(6)>1 || af(6)<-1
    counter = counter+1;

    disp('焦点超出范围;正在重新尝试(随机)...');

    a0 = [0 0 0 0 0, 2*rand-1.0];

    [af,resnorm] = lsqnonlin(@(x) costRectif(x,width,height,ml,mr), a0,...
        [-pi/2, -pi/2, -pi/2, -pi/2, -pi/2, -1.5], [pi/2, pi/2, pi/2, pi/2, pi/2, 1.5],options);

    if counter > 20
        warning('找不到范围内的焦点')
        break
    end

end

f =3^af(6)*(width+height);
% disp(['焦距:f = ' num2str(f)]);

测试

f = compIntrinsic (ml,mr,width,height);%ml,mr 一个2xn矩阵的匹配点对.width,height 是图像的长,宽
disp(['焦距:f = ' num2str(f)]);

结果
焦距:f = 892.7031
基本准确。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值