【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matchingharmonylab
公開URL:https://arxiv.org/pdf/2404.19174
出典:Guilherme Potje, Felipe Cadar, Andre Araujo, Renato Martins, Erickson R. ascimento: XFeat: Accelerated Features for Lightweight Image Matching, Proceedings of the 2024 IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR) (2023)
概要:リソース効率に優れた特徴点マッチングのための軽量なアーキテクチャ「XFeat(Accelerated Features)」を提案します。手法は、局所的な特徴点の検出、抽出、マッチングのための畳み込みニューラルネットワークの基本的な設計を再検討します。特に、リソースが限られたデバイス向けに迅速かつ堅牢なアルゴリズムが必要とされるため、解像度を可能な限り高く保ちながら、ネットワークのチャネル数を制限します。さらに、スパース下でのマッチングを選択できる設計となっており、ナビゲーションやARなどのアプリケーションに適しています。XFeatは、高速かつ同等以上の精度を実現し、一般的なラップトップのCPU上でリアルタイムで動作します。
セル生産方式におけるロボットの活用には様々な問題があるが,その一つとして 3 体以上の物体の組み立てが挙げられる.一般に,複数物体を同時に組み立てる際は,対象の部品をそれぞれロボットアームまたは治具でそれぞれ独立に保持することで組み立てを遂行すると考えられる.ただし,この方法ではロボットアームや治具を部品数と同じ数だけ必要とし,部品数が多いほどコスト面や設置スペースの関係で無駄が多くなる.この課題に対して音𣷓らは組み立て対象物に働く接触力等の解析により,治具等で固定されていない対象物が組み立て作業中に運動しにくい状態となる条件を求めた.すなわち,環境中の非把持対象物のロバスト性を考慮して,組み立て作業条件を検討している.本研究ではこの方策に基づいて,複数物体の組み立て作業を単腕マニピュレータで実行することを目的とする.このとき,対象物のロバスト性を考慮することで,仮組状態の複数物体を同時に扱う手法を提案する.作業対象としてパイプジョイントの組み立てを挙げ,簡易な道具を用いることで単腕マニピュレータで複数物体を同時に把持できることを示す.さらに,作業成功率の向上のために RGB-D カメラを用いた物体の位置検出に基づくロボット制御及び動作計画を実装する.
This paper discusses assembly operations using a single manipulator and a parallel gripper to simultaneously
grasp multiple objects and hold the group of temporarily assembled objects. Multiple robots and jigs generally operate
assembly tasks by constraining the target objects mechanically or geometrically to prevent them from moving. It is
necessary to analyze the physical interaction between the objects for such constraints to achieve the tasks with a single
gripper. In this paper, we focus on assembling pipe joints as an example and discuss constraining the motion of the
objects. Our demonstration shows that a simple tool can facilitate holding multiple objects with a single gripper.
15. そして実装を書く
def gcm(a, b) !
4!
end !
おい! ちゃんと計算しろ!
でもテストは通るからOK
describe 'gcm' do !
it 'should return 4 that gcm(12, 28)' do !
expect(gcm(12, 28)).to eq 4 !
end !
end
15
16. さらにテストを書く
describe 'gcm' do !
it 'should return 4 that gcm(12, 28)' do !
expect(gcm(12, 28)).to eq 4 !
end !
it 'should return 7 that gcm(21, 28)' do !
expect(gcm(21, 28)).to eq 7 !
end !
end!
基本的なケース2: 21と28なら7
16
17. 実装を修正する
def gcm(a, b) !
a == 12 ? 4 : 7
end !
おい! ちゃんと計算しろって!!!
でもテストは通るからOK
describe 'gcm' do !
it 'should return 4 that gcm(12, 28)' do !
expect(gcm(12, 28)).to eq 4 !
end !
it 'should return 7 that gcm(21, 28)' do !
expect(gcm(21, 28)).to eq 7 !
end !
end!
17
18. よろしい、ならば戦争だ
describe 'gcm' do !
it 'should return 4 that gcm(12, 28)' do !
expect(gcm(12, 28)).to eq 4 !
end !
it 'should return 7 that gcm(21, 28)' do !
expect(gcm(21, 28)).to eq 7 !
end !
it 'should return 7 that gcm(28, 21)' do !
大小入れ替え
expect(gcm(28, 21)).to eq 7 !
end !
it 'should return 28 that gcm(28, 28)' do ! 同じ数
expect(gcm(28, 28)).to eq 28 !
end !
it 'should raise error that gcm(-1, 6)' do !
変な値→例外来い
expect{gcm(-1, 6)}.to raise_error !
end !
end!
18
19. そろそろ真面目に実装する
def gcm(a, b) !
raise ArgumentError.new if a < 1 || b < 1 !
if a < b !
gcm(b, a)
else !
if a % b == 0 !
b
else !
gcm(b, a % b)
end !
end !
end !
※テストに通りました
19
28. RSpecの雰囲気
describe Array, "when empty" do !
何についてテストするのかを書ける
before do !
@empty_array = [] !
end !
before
に各テスト実行前の共通処理
it "should be empty" do !
@empty_array.should be_empty !
テスト内容をより明確に書ける
end !
テスト条件の記述が読み易い
it "should size 0" do !
@empty_array.size.should == 0 !
end !
after do !
@empty_array = nil !
aberに各テスト実行後の共通処理
end !
end!
28
29. RSpecは内容を仕様書的に出力できる
describe Array, "when empty" do !
before do !
@empty_array = [] !
end !
it "should be empty" do !
@empty_array.should be_empty !
end !
it "should size 0" do !
@empty_array.size.should == 0 !
こんな感じ
%
spec
-‐fs
array_spec.rb
Array
when
empty
-‐
should
be
empty
-‐
should
size
0
end !
after do !
@empty_array = nil !
end !
end!
29
47. Stubで振る舞いを変える
Time
に
now
が来たら特定の値を返すように仕込む
describe 'is_sunday?' do !
it 'should be true if today is Sunday' do !
# 2014/2/2 は 日曜日
Time.stub(:now).and_return(Time.new(2014, 2, 2)) !
expect(is_sunday?).to eq true !
end !
it 'should be false if today is Saturday' do !
# 2014/2/1 は 土曜日
Time.stub(:now).and_return(Time.new(2014, 2, 1)) !
expect(is_sunday?).to eq false !
end !
end!
47
55. とりあえずテスト書いて実行
describe SomeClass do !
※中身がない
describe 'print_prefecture' do !
it 'should print 東京都 when zipcode=1030000' !
it 'should not print anything when zipcode=1030900' !
end !
end !
SomeClass
print_prefecture
should
print
東京都 when
zipcode=1030000
(PENDING:
Not
yet
implemented)
should
not
print
anything
when
zipcode=1030900
(PENDING:
Not
yet
implemented)
Finished
in
0.00034
seconds
2
examples,
0
failures,
2
pending
「Pending」になる。これもSpec系の特徴。
「失敗」とは少し違う。「まだ書いてないよ」という状態。
55
57. とりあえずこんな感じで
class SomeClass !
def print_prefecture(zipcode) !
prefecture = get_prefecture(zipcode) !
ここで都道府県が戻る想定
!
if prefecture !
puts prefecture !
end !
end !
end !
Nil
じゃなければ出力
57
58. Stubでホワイトボックステスト
describe SomeClass do !
describe 'print_prefecture' do !
before do !
@obj = SomeClass.new !
@obj
に毎回Objectを入れる共通処理
end !
it 'should print 東京都 when zipcode=1030000' do !
@obj.stub(:get_prefecture => '東京都')
get_prefecture
が 東京都
end !
end !
end!
を返すならば
あれ?
Puts
したかってどうテストする?
出力したか、という判定をするのが難しい。
→
少し工夫が必要
※Kernel.puts
を調べれば良いんですけどね。今回はこういう想定で。
58
59. 実装コードをテストしやすく修正
class SomeClass !
def print_prefecture(zipcode) !
prefecture = get_prefecture(zipcode) !
if prefecture !
output(prefecture)
end !
end !
!
出力する、というのを呼び出すようにする
def output(str) !
puts str !
end !
end !
59
60. Output()をCallすればOKと考える
it 'should print 東京都 when zipcode=1030000' do !
get_prefecture
が 東京都 を返すなら
@obj.stub(:get_prefecture => '東京都')
@objは
output(‘東京都’)
が呼ばれることが期待される
expect(@obj).to receive(:output).with('東京都') !
じゃあ、実行しましょう
@obj.print_prefecture('1030000') !
end !
となる
60
61. Outputされないケースも追加
describe SomeClass do !
describe 'print_prefecture' do !
before do !
@obj = SomeClass.new !
end !
it 'should print 東京都 when zipcode is in 東京都 area' do !
@obj.stub(:get_prefecture => '東京都')
expect(@obj).to receive(:output).with('東京都') !
@obj.print_prefecture('1030000') !
end !
it 'should not print anything when zipcode doesnot exist' do !
Exampleの文言も修正する
nil) !
expect(@obj).not_to receive(:output)
@obj.stub(:get_prefecture =>
@obj.print_prefecture('1030900') !
end !
end !
end !
!
get_prefectureがnilの時も追加する
仮に:get_prefecture
が
nil
期待:
output()は呼ばれない
61
62. テスト実行!
SomeClass
print_prefecture
should
print
東京都 when
zipcode
is
in
東京都 area
should
not
print
anything
when
zipcode
doesnot
exist
Finished
in
0.00124
seconds
2
examples,
0
failures
テストが通った
62
63. 続けて細かい実装を先に書いてしまう
勢いってものがあるじゃないですか
require 'net/http' !
require 'rexml/document' !
class SomeClass !
def print_prefecture(zipcode) !
prefecture = get_prefecture(zipcode) !
if prefecture !
output(prefecture) !
end !
end !
def get_prefecture(zipcode) !
xml_data = Net::HTTP.get(URI.parse("http://zip.cgis.biz/xml/zip.php?zn=#{zipcode}")) !
scan_prefecture(xml_data) !
end !
def scan_prefecture(xml_data) !
attr_state = REXML::Document.new(xml_data).elements['//@state'] !
attr_state ? attr_state.value : nil !
end !
def output(str) !
puts str !
end !
end !
63
get_prefecture()
と
scan_prefecture()
に分けた
64. テスト: get_prefecture()
実装コード
def get_prefecture(zipcode) !
xml_data = Net::HTTP.get(URI.parse("http://zip.cgis.biz/xml/zip.php?zn=#{zipcode}")) !
scan_prefecture(xml_data) !
end !
テストコード
describe 'get_prefecture' do !
it 'should call API Request with zipcode' do !
expect(Net::HTTP).to receive(:get) !
expect(URI).to receive(:parse).with(/zn=1030000/) !
@obj.get_prefecture('1030000') !
end !
!
it 'should return scan_prefecture result' do !
Net::HTTP.stub(:get => 'SOME DATA') !
期待:HTTP.get
が呼ばれる
期待:URI.parse
が呼ばれて、
引数は
/zn=103000/
の
正規表現とMatchするはず。
expect(@obj).to receive(:scan_prefecture).with('SOME DATA').and_return('RESULT') !
expect(@obj.get_prefecture('1030000')).to eq('RESULT') !
end !
end !
仮に: HTTP.get
が
‘SOME
DATA’を返すとして、
期待:
@obj.scan_prefecture(‘SOME
DATA’)が呼ばれる
その結果が
‘RESULT’
だったとして、
期待:
@obj.get_prefecture()
の返り値は
’RESULT’
になる。
64
65. テスト: scan_prefecture()
実装コード
def scan_prefecture(xml_data) !
attr_state = REXML::Document.new(xml_data).elements['//@state'] !
attr_state ? attr_state.value : nil !
end !
テストコード
describe 'scan_prefecture' do !
it 'should return 東京都 if the xml data is so' do !
expect(@obj.scan_prefecture(D1)).to eq '東京都'
end !
!
期待:
scan_pefecture(sample1)な
ら戻り値は 東京都 である
!
it 'should return nil if the xml data doesnot contain pref info' do !
expect(@obj.scan_prefecture(D2)).to eq nil !
end !
end !
期待:
scan_pefecture(sample2)な
ら戻り値は
nil
である
65
※ブラックボックスになっている
66. describe SomeClass do !
before do !
@obj = SomeClass.new !
end !
describe 'print_prefecture' do !
it 'should print 東京都 when zipcode is in 東京都 area' do !
@obj.stub(:get_prefecture => '東京都')
expect(@obj).to receive(:output).with('東京都') !
@obj.print_prefecture('1030000') !
end !
it 'should not print anything when zipcode doesnot exist' do !
@obj.stub(:get_prefecture => nil) !
expect(@obj).not_to receive(:output) !
@obj.print_prefecture('1030900') !
end !
end !
describe 'get_prefecture' do !
it 'should call API Request with zipcode' do !
expect(Net::HTTP).to receive(:get) !
expect(URI).to receive(:parse).with(/zn=1030000/) !
@obj.get_prefecture('1030000') !
end !
it 'should return scan_prefecture result' do !
Net::HTTP.stub(:get => 'SOME DATA') !
expect(@obj).to receive(:scan_prefecture).with('SOME DATA').and_return('RESULT') !
expect(@obj.get_prefecture('1030000')).to eq('RESULT') !
end !
end !
describe 'scan_prefecture' do !
it 'should return 東京都 if the xml data is so' do !
expect(@obj.scan_prefecture(D1)).to eq '東京都'
end !
it 'should return nil if the xml data doesnot contain pref info' do !
expect(@obj.scan_prefecture(D2)).to eq nil !
end !
end !
end !
テスト全体
66
67. テスト実行
SomeClass
print_prefecture
should
print
東京都 when
zipcode
is
in
東京都 area
should
not
print
anything
when
zipcode
doesnot
exist
get_prefecture
should
call
API
Request
with
zipcode
should
return
scan_prefecture
result
scan_prefecture
should
return
東京都 if
the
xml
data
is
so
should
return
nil
if
the
xml
data
doesnot
contain
pref
info
Finished
in
0.00804
seconds
6
examples,
0
failures
テストが通った
67