计算机视觉:朗伯光度立体法(Lambertian Photometric Stereo)

计算机视觉:朗伯光度立体法(Lambertian Photometric Stereo)

  • 光度立体法简介
  • 朗伯光度立体法算法原理
  • 朗伯光度立体法matlab程序
  • 示例
    • Albedo图
    • Normal图
    • Re_rendered图
  • 参考文献

光度立体法简介

光度立体法,即Photometric Stereo, 最早是由当时在MIT的人工智能实验室的Robert J. Woodham教授在1978年左右提出。他在1979年的论文《Photometric stereo: A reflectance map technique for determining surface orientation from image intensity》,以及1980年的论文《Photometric Method for Determining Surface Orientation from Multiple Images》中比较系统的阐述了整套理论框架。光度立体法可以根据二维纹理信息提取出三维模型,其典型应用是检测物体表面微小变化。

朗伯光度立体法基于Woodham算法,Woodham在论文中提出三个基本假设。在这三个基本假设下完成整套理论框架的推演。这三个基本假设分别是:

  1. 假定相机是无畸变成像,也就是说必须使用远心镜头或者长焦镜头。
  2. 假定每一个光源发射的光束都是平行且均匀的,也就是说必须使用具有均匀强度的远心照明光源,或者使用远距离的点光源代替。
  3. 物体必须具有朗伯(lambertian)反射特性,即它必须以漫反射的方式反射入射光。

朗伯光度立体法的大致思路是:
当相机和目标物体相对位置固定不变时,使用不同方向的光源照射同一目标物体,相机可以拍摄到目标物体带有不同明暗分布的图像(至少需要三张图),再通过求解基于朗伯反射原理的反射方程组,求解目标表面的法向分布或者albedo图。

带有远心镜头的相机必须与被测物体表面垂直安装,在采集多幅图像时,一定要保证相机和物体不被移动。相反,对于采集至少三张的灰度图像,其每次取像的照明方向必须改变(相对于相机)。对于采集的多张图像中的每一幅图,照明方向必须指定Slants和Tilts两个参数角度,其描述了相对于当前场景的光照角度。为了更好的理解这两个参数含义,我们假定光源射出的光束是平行光,镜头是远心镜头,相机垂直于物体表面。
在这里插入图片描述
在这里插入图片描述

朗伯光度立体法算法原理

根据Lambert模型:
I = ρ   L ⋅ N \textbf{I} = \rho\ \textbf{L}\cdot\textbf{N} I=ρ LN
式中, ρ \rho ρ 为表面反射率(albedo),其值介于0 - 1之间,反映了物体表面特性; N \textbf{N} N 为表面法线(normal); L \textbf{L} L 为照明方向。将 ρ \rho ρ N \textbf{N} N 合并起来用 G \textbf{G} G来表示,则有:
I = L T G . \textbf{I} = \textbf{L}^T\textbf{G}. I=LTG.
每个像素位置对应的 G \textbf{G} G是三维向量(方向为normal,模长为albedo),因此单个光源无法求解该方程,至少需要三个不同位置的光源,求解得到三个未知量。
由最小二乘法:
min ⁡ G ∣ ∣ I − L T G ∣ ∣ 2 \mathop{\min}\limits_{\textbf{G}} ||\textbf{I}-\textbf{L}^T\textbf{G}||^2 Gmin∣∣ILTG2
可以求得:
G = ( L L T ) − 1 LI \textbf{G} = (\textbf{L}\textbf{L}^T)^{-1}\textbf{L}\textbf{I} G=(LLT)1LI
我们求得 G \textbf{G} G 的模长就是albedo:
ρ = ∣ ∣ G ∣ ∣ \rho = ||\textbf{G}|| ρ=∣∣G∣∣
G \textbf{G} G 归一化后的单位向量矩阵就是normal:
N = G ∣ ∣ G ∣ ∣ \textbf{N} = \frac{\textbf{G}}{||\textbf{G}||} N=∣∣G∣∣G

朗伯光度立体法matlab程序

注:此代码只涉及核心算法,不包含数据的读入,与结果的输出。

function [Albedo, Normal, Re_rendered] = Photometric_Stereo(data)

assert(size(data.imgs, 1)==size(data.s, 1), 'Size mismatched!');
num = size(data.imgs, 1);

% Get image dimensions
im = data.imgs{1};
[im_h, im_w, ~] = size(im);
% Initialize T, a im_h-by-im_w-by-num matrix, whose (h, w, :) holds 
% the intensities at (h, w) for all p different lightings
im_T = zeros(im_h, im_w, num);
% Initialize im_R, a im_h-by-im_w-by-num matrix
im_R = zeros(im_h, im_w, num);
% Initialize im_G, a im_h-by-im_w-by-num matrix
im_G = zeros(im_h, im_w, num);
% Initialize im_B, a im_h-by-im_w-by-num matrix
im_B = zeros(im_h, im_w, num);

% For each image
for idx = 1:num
    im = data.imgs{idx};
    imGray = rgb2gray(im);
    % Loop thru each pixel
    for h = 1:im_h
        for w = 1:im_w
            % If in the mask
            if data.mask(h, w)
                im_R(h, w, idx) = im(h, w, 1);
                im_G(h, w, idx) = im(h, w, 2);
                im_B(h, w, idx) = im(h, w, 3);
                im_T(h, w, idx) = imGray(h,w);
            end
        end
    end
end

% Initialize Normal, a im_h-by-im_w-by-3 matrix
Normal = zeros(im_h, im_w, 3);
% Initialize Albedo, a im_h-by-im_w-by-1 matrix
Albedo = zeros(im_h, im_w, 3);
% Initialize Re_rendered, a im_h-by-im_w-by-3 matrix
Re_rendered = zeros(im_h, im_w, 3);

% Loop thru each location
for h = 1:im_h
    for w = 1:im_w
        % If in the mask
        if data.mask(h, w)
           %% Normal 
            % Lightings
            L = data.s;
            % Intensities
            I = reshape(im_T(h, w, :), [num, 1]);
            % Dealing with shadows and highlights
            for k = 1:10
                max_index = find(I==max(I));
                I(max_index) = [];
                L(max_index,:) = [];
                min_index = find(I==min(I));
                I(min_index) = [];
                L(min_index,:) = [];
            end
            % Solve surface normals and albedo
            G = (L.'*L)\(L.'*I);
            if norm(G) ~= 0
                % Normalize n
                n = G./norm(G);
            else
                n = [0; 0; 0];
            end
            % Save
            Normal(h, w, :) = n;
           %% Albedo
            % a_R
            L = data.s;
            I_R = reshape(im_R(h, w, :), [num, 1]);
            for k = 1:10
                max_index = find(I_R==max(I_R));
                I_R(max_index) = [];
                L(max_index,:) = [];
                min_index = find(I_R==min(I_R));
                I_R(min_index) = [];
                L(min_index,:) = [];
            end
            G_R = (L.'*L)\(L.'*I_R);
            a_R = norm(G_R);
            Albedo(h, w, 1) = a_R;
            % a_G
            L = data.s;
            I_G = reshape(im_G(h, w, :), [num, 1]);
            for k = 1:10
                max_index = find(I_G==max(I_G));
                I_G(max_index) = [];
                L(max_index,:) = [];
                min_index = find(I_G==min(I_G));
                I_G(min_index) = [];
                L(min_index,:) = [];
            end
            G_G = (L.'*L)\(L.'*I_G);
            a_G = norm(G_G);
            Albedo(h, w, 2) = a_G;
            % a_B
            L = data.s;
            I_B = reshape(im_B(h, w, :), [num, 1]);
            for k = 1:10
                max_index = find(I_B==max(I_B));
                I_B(max_index) = [];
                L(max_index,:) = [];
                min_index = find(I_B==min(I_B));
                I_B(min_index) = [];
                L(min_index,:) = [];
            end
            G_B = (L.'*L)\(L.'*I_B);
            a_B = norm(G_B);
            Albedo(h, w, 3) = a_B;
            %% Re_rendered
            Re_rendered(h, w, :) = [a_R;a_G;a_B]*dot(n,[0;0;1]);
        end
    end
end

完整程序请移步至此链接下载

示例

Albedo图

反照率图:
反照率图

Normal图

以RGB线性编码的法线贴图:
以RGB线性编码的法线贴图

Re_rendered图

在照明方向和观察方向一致时,利用normal和albedo图重新渲染的图片:

在照明方向和观察方向一致时,利用normal和albedo图重新渲染的图片

参考文献

光度立体简介
Halcon 光度立体法(photometric_stereo)详解z

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/281912.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Layui弹窗带标签可切换图表的应用Demo

提供Layui弹窗带页签的Demo写法 文章目录 前言一、展示效果二、详细代码1.代码2.简单释义 总结 前言 之前因为有需求,需要开发Layui的弹出框,同时弹窗框需要支持,页签点击切换内容,特此整理了这一篇文章,提供给需要的…

【Image】超硬核数学推导——WGAN的先“破”后“立”

GAN的实现 上一篇文章中我们说到了GAN的数学解释 min ⁡ G max ⁡ D V ( D , G ) E x ∼ p data ( x ) [ log ⁡ D ( x ) ] E z ∼ p z ( z ) [ log ⁡ ( 1 − D ( G ( z ) ) ) ] − log ⁡ 4 2 J S D ( p data ∥ p g ) ≥ − log ⁡ 4 , where [ p d a t a p g ] \mi…

力扣题目学习笔记(OC + Swift)24. 两两交换链表中的节点

24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 方法一、递归 首先定义递归终止条件: …

ssm基于web 的个人时间管理系统+vue论文

基于web 的个人时间管理系统的设计与实现 摘要 当下,正处于信息化的时代,许多行业顺应时代的变化,结合使用计算机技术向数字化、信息化建设迈进。传统的个人时间信息管理模式,采用人工登记的方式保存相关数据,这种以人…

DsPdf:GcPdf 7.0 for NET Crack

DsPdf:GcPdf 7.0 用于全面文档控制的功能丰富的 C# .NET PDF API 库 PDF 文档解决方案(DsPdf,以前称为 GcPdf)可让您快速、高效地生成文档,且无需依赖任何内存。 在 C# .NET 中生成、加载、编辑和保存 PDF 文档 支持多种语言的全…

为什么不应该在 SAN/NAS 设备上运行 MinIO(还有一个例外)

我们想分享一下我们在 SAN/NAS 设备上运行 MinIO 的想法。首先,您可以在 SAN/NAS 设备上运行 MinIO。虽然这是可能的,但这不是一个好主意,我们强烈建议客户不要采用这种方法。不要让友好的邻居 SAN/NAS 设备供应商在没有先阅读以下内容的情况…

软件有效找不到dll文件,五种可靠的解决dll方法分享

电脑已经成为我们生活和工作中不可或缺的工具。然而,由于各种原因,电脑可能会出现一些问题,其中之一就是“电脑提示dll文件缺失”。这个问题可能会给我们的生活和工作带来很大的困扰,因此,我希望通过分享我的心得体会&…

学习路径概览

根据codewave 低代码官方的资料,我们以一个简单的初级采购管理系统为例,带大家进行学习。学习的案例框架如下: https://ik4mh7u2np.feishu.cn/docx/NjyEd9qD5oElkoxJhapc3fV4nPe?fromfrom_copylink​​​​​​​ 主要分为以下四个学习模块

ros2 run传递参数的格式

ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -r /cmd_vel:/model/vehicle_blue/cmd_vel #这个只能用于重命名节点名称可以用以下语法直接从命令行中设置参数: ros2 run package_name executable_name --ros-args -p param_name:param_value …

centos7.9 TCP 加速

BBR是谷歌开发的新的TCP加速算法,在网络状况不好的服务器上开启TCP的bbr,可以在无需增加任何硬件投入的情况下实现网络加速,并且客户端无需做任何配置,因此使用起来非常的方便。TCP加速对网络状况较好的内网环境,或者大…

【阅读笔记】Semi-supervised Domain Adaptation in Graph Transfer Learning

Background 真实世界的图上节点的标签数据是很难拿到的。 因此图转移学习被提出将知识从标记的源图转移出来,以帮助预测域变化的目标图中节点的标签。 尽管图迁移学习算法取得了重大进展,但它们通常假定源图中的所有节点都被标记出来了。 因此文章定义…

商品销售数据爬取分析可视化系统 爬虫+机器学习 淘宝销售数据 预测算法模型 大屏 大数据毕业设计(附源码)✅

毕业设计:2023-2024年计算机专业毕业设计选题汇总(建议收藏) 毕业设计:2023-2024年最新最全计算机专业毕设选题推荐汇总 🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题&#xff…

三角函数两角和差公式推导

一.几何推理 1.两角和公式 做一斜边为1的直角△ABC,任意旋转非 k Π , k N kΠ,kN kΠ,kN,补充如图,令 ∠ A B C ∠ α , ∠ C B F ∠ β ∠ABC∠α,∠CBF∠β ∠ABC∠α,∠CBF∠β ∴ ∠ D B F ∠ D B A ∠ α ∠ β 90 , ∠ D A …

OpenEular23.09(欧拉)操作系统为企业搭建独立的K8S集群环境,详细流程+截图

一.环境; win10,vmware16 pro,openeular23.09 集群模式:一主二从 主机硬件配置 主机名IP角色CPU内存硬盘k8s-master01192.168.91.100master4C4G40Gk8s-worker02192.168.91.101worker(node)4C4G40Gk8s-worker03192.168.91.102wor…

toto的2023年终总结

第一次写年终总结,其实顺带是把大学四年的学习都给总结了一下,称之为大学总结更为合适吧? 其实把年终总结发在CSDN上有些不适,之前一直想着搭一个自己的博客也因为种种事情一直没有完成, 索性发在这里了,作…

什么是边缘案例测试?如何查找并确定优先级

何为边缘情况? 在极端条件下发生的情况被称为边缘情况,有时候也叫边界情况,在功能、回归、单元和性能测试中都会应用。如果质量保证团队知道某项功能的最大和最小负载,他们就能防止这些情况发生。当用户不按照程序的预期工作流程…

Windows不同的域名由不同的DNS服务器解析

gpedit.msc(组策略)-计算机配置-Windows设置-域名解析策略 本次改动在注册表中体现的位置。 计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Dnscache\Parameters\DnsPolicyConfig\{666881c9-5525-434b-a62a-2ed5c61d53e5} 计算机\HKEY_LOCAL_MACHINE\SYSTEM\Cur…

⑩①【缓存】Redis持久化 RDB + AOF

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ ⑩①Redis持久化 RDB AOF Redis数据快照 - RD…

XXE注入漏洞总结

XXE和XML概念 XML被设计为传输和存储数据,XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素,其焦点是数据的内容,其把数据从HTML分离,是独立于软件和硬件的信息传输工具。XXE漏洞全称XML Externa…