Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Halideによる画像処理について
Search
saturday06
March 27, 2017
Programming
2.8k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Halideによる画像処理について
saturday06
March 27, 2017
More Decks by saturday06
See All by saturday06
HLSの遅延を350ms+ネットワーク遅延分まで削減する
saturday06
3
2.4k
Other Decks in Programming
See All in Programming
AHC070解法紹介
eijirou
0
130
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
230
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
330
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
220
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
280
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.8k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
210
WebRTC映像をAirPlayに対応させる挑戦.pdf
monolithic_adam
0
290
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
1
350
What We Talk About When We Talk About XP
m_seki
2
660
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
260
SREの越境 / SRE Collaboration
y0hgi
2
260
Featured
See All Featured
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
My Coaching Mixtape
mlcsv
0
320
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
500
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.6k
Between Models and Reality
mayunak
4
460
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Designing Experiences People Love
moore
143
24k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Raft: Consensus for Rubyists
vanstee
142
7.7k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
280
Transcript
Halideによる 画像処理について 2017/03/14 ピクシブ株式会社 茂木 勇
目次 - Halide概要 - Halideでぼかし処理 - Halideで画像縮小処理 - ベンチマーク
Halideとは? - C++の画像処理ライブラリ - 「ハロゲン化合物」という意味 - ライブラリではあるが「ハイパフォーマンスな画像処理を行うことができる新しい言 語」と名乗っている - 開発者「1500行のマルチスレッドとアセンブラで最適化されたPhotoshopのとある
フィルタのC++のコードを3ヶ月で10倍高速化した」 - http://halide-lang.org/assets/lectures/Halide_CVPR_intro.pdf
None
None
Halideの特徴 - C++の文法で数式を記述し、Halideが内部に持っているLLVMでコンパイルするこ とで画像処理用の関数を生成する - 数式自体をコンパイル、最適化をするので「縮小して輝度を上げる」など複数の画 像処理を組み合わせた際にパフォーマンスが向上する可能性がある - SSE,AVX,NEON等CPUのSIMD命令及びCUDA,OpenCLなどGPUを使った最適 化に対応している。
- CPU用に書いた処理をほとんど変更せず GPUでも動かせる
例: 近傍4ピクセルを使ったぼかし処理 blur(x, y) = (src(x-1,y) + src(x,y-1) + src(x,y)
+ src(x+1,y) + src(x,y+1))/5
例: 近傍4ピクセルを使ったぼかし処理(Halide版) Func src = …; Func blur; Var x,
y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5;
例: 近傍4ピクセルを使ったぼかし処理(Halide版) Func src = BoundaryConditions::repeat_edge(...); Func blur; Var x,
y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; 画像端のデータを繰り返す
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; 入力画像データの定義
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); これらを内部のLLVMで コンパイルして、 Cのライブラリとして出力
例: 近傍4ピクセルを使ったぼかし処理(Halide版) #include <Halide.h> int main() { using namespace Halide;
ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); return 0; }
#include <Halide.h> int main() { using namespace Halide; ImageParam input(type_of<uint8_t>(),
2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版)
#include <Halide.h> int main() { using namespace Halide; ImageParam input(type_of<uint8_t>(),
2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; blur.compile_to_static_library("blur", {input}); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版)
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5;
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = (src(x-1,y)+src(x,y-1)+src(x,y)+src(x+1, y)+src(x,y+1))/5; 画素値は8bit整数のため 足し算結果がオーバーフローしている
例: 近傍4ピクセルを使ったぼかし処理(Halide版) ImageParam input(type_of<uint8_t>(), 2); Func src = BoundaryConditions::repeat_edge(input); Func
blur; Var x, y; blur(x, y) = src(x-1,y)/5+src(x,y-1)/5+src(x,y)/5+src(x+1, y)/5+src(x,y+1)/5; オーバーフローしにくいように修正 (型変換とかもできる)
#include <Halide.h> int main() { using namespace Halide; ImageParam input(type_of<uint8_t>(),
2); Func src = BoundaryConditions::repeat_edge(input); Func blur; Var x, y; blur(x, y) = src(x-1,y)/5+src(x,y-1)/5+src(x,y)/5+src(x+1, y)/5+src(x,y+1)/5; blur.compile_to_static_library("blur", {input}); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版)
blur(x, y) = src(x-1,y)/5+src(x,y-1)/5+src(x,y)/5+src(x+1, y)/5+src(x,y+1)/5; blur.gpu_tile(x, y, 16, 16); auto
target = Halide::get_host_target(); target.set_feature(Target::OpenCL); blur.compile_to_static_library("blur", {input}, "", target); return 0; } 例: 近傍4ピクセルを使ったぼかし処理(Halide版) GPU使う場合
画像縮小処理 - pixivではサムネイル作成用の画像縮小にffmpeg(libswscale) を用いているが、幾つかの問題点があり乗り換え先を検討し ている - 高速で、高品質な縮小処理が求められている - halideが代わりとして使えないか?
例: Nearest Neighber法による画像縮小処理 縮小
例: Nearest Neighber法による画像縮小処理 out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) in画像 out画像
例: Nearest Neighber法による画像縮小処理(Halide) out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y))
例: Nearest Neighber法による画像縮小処理(Halide) Func out; Var out_x, out_y; out(out_x, out_y)
= in(nearest_in_x(out_x),nearest_in_y(out_y)) 出力変数、関数定義
例: Nearest Neighber法による画像縮小処理(Halide) ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func
out; Var out_x, out_y; out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) 入力画像、出力サイズ 定義
例: Nearest Neighber法による画像縮小処理(Halide) ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func
nearest_in_x; Var x; nearest_in_x(x) = x * in.width() / out_width; Func out; Var out_x, out_y; out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) 「最近傍のx座標を取得」関数定義
例: Nearest Neighber法による画像縮小処理(Halide) ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func
nearest_in_y; Var y; nearest_in_y(y) = y * in.height() / out_height; Func nearest_in_x; Var x; nearest_in_x(x) = x * in.width() / out_width; Func out; Var out_x, out_y; out(out_x, out_y) = in(nearest_in_x(out_x),nearest_in_y(out_y)) 「最近傍のy座標を取得」関数定義
例: Nearest Neighber法による画像縮小処理(Halide) #include <Halide.h> int main() { using namespace
Halide; ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func nearest_in_x; Var x; nearest_in_x(x) = (x * in.width() + out_width / 2) / out_width; Func nearest_in_y; Var y; nearest_in_y(y) = (y * in.height() + out_height / 2) / out_height; Func out; Var out_x, out_y; out(out_x, out_y) = BoundaryConditions::repeat_edge(in)(nearest_in_x(out_x), nearest_in_y(out_y)); out.compile_to_static_library("nearest_neighber", {in, out_width, out_height}); return 0; } 現実の問題に対するワークアラウンドとか追加
例: Nearest Neighber法による画像縮小処理(Halide) #include <Halide.h> int main() { using namespace
Halide; ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func nearest_in_x; Var x; nearest_in_x(x) = (x * in.width() + out_width / 2) / out_width; Func nearest_in_y; Var y; nearest_in_y(y) = (y * in.height() + out_height / 2) / out_height; Func out; Var out_x, out_y; out(out_x, out_y) = BoundaryConditions::repeat_edge(in)(nearest_in_x(out_x), nearest_in_y(out_y)); out.compile_to_static_library("nearest_neighber", {in, out_width, out_height}); return 0; } in画像
例: Nearest Neighber法による画像縮小処理(Halide) #include <Halide.h> int main() { using namespace
Halide; ImageParam in(type_of<uint8_t>(), 2); Param<uint32_t> out_width, out_height; Func nearest_in_x; Var x; nearest_in_x(x) = (x * in.width() + out_width / 2) / out_width; Func nearest_in_y; Var y; nearest_in_y(y) = (y * in.height() + out_height / 2) / out_height; Func out; Var out_x, out_y; out(out_x, out_y) = BoundaryConditions::repeat_edge(in)(nearest_in_x(out_x), nearest_in_y(out_y)); out.compile_to_static_library("nearest_neighber", {in, out_width, out_height}); return 0; } in画像 out画像
ベンチマーク 内容: サイズ1600x3200のグレースケール画像を320x480に様々な方式で縮小 環境: MacBook Pro (Retina, 15-inch, Mid 2015)
Processor Name: Intel Core i7 Processor Speed: 2.2 GHz Total Number of Cores: 4 Memory: 16 GB GPU: Intel Iris Pro 1536 MB
ベンチマーク結果(小さい値だとより良い) Benchmark Time CPU ------------------------------------------------------- HalideResizeNearestNeighber 2083577 ns 2081819 ns
HalideResizeBilinear 10228914 ns 10225705 ns HalideResizeGpuBilinear 947467 ns 736395 ns FfmpegResizeFastBilinear 1418483 ns 1416548 ns FfmpegResizeBilinear 6036412 ns 6033964 ns FfmpegResizeLanczos3 18074324 ns 18070590 ns
Halideの特徴(再掲) - C++の文法で数式を記述し、Halideが内部に持っているLLVMでコンパイルするこ とで画像処理用の関数を生成する - 数式自体をコンパイル、最適化をするので「縮小して輝度を上げる」など複数の画 像処理を組み合わせた際にパフォーマンスが向上する可能性がある - x86,arm等CPUのSIMD命令及びCUDA、OpenCLを使った最適化に対応してい る。
- CPU用に書いた処理をほとんど変更せず GPUでも動かせる
ベンチマーク2 内容: サイズ1600x3200のグレースケール画像をネガポジ変換をして から320x480にバイリニア法で縮小
ベンチマーク結果2(小さい値だとより良い) Benchmark Time CPU ----------------------------------------------------------- HalideResizeBilinear 10228914 ns 10225705 ns
HalideNegateResizeBilinear 10417060 ns 10413506 ns FfmpegResizeBilinear 6036412 ns 6033964 ns OpenCVNegateFfmpegResizeBilinear 9038528 ns 9036810 ns
ベンチマーク結果まとめ - FFmpegのような職人芸コードに比べて速度60%くらいのコードが生成される - GPUにオフロードすることで、CPUでは実現不可能な速度で処理ができる - GPUの職人芸にどのくらい及んでいるのかはまだ未検証 - 数式DSLを内部のLLVMでコンパイルするため、複数の画像処理を組み合わせた際 には職人芸コードの組み合わせよりも高速なコードが生成される可能性がある