Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Halideによる画像処理について
Search
saturday06
March 27, 2017
Programming
2.7k
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
AIを活用したE2Eテスト実装効率化のあゆみ / ebisu-mobile-14-kotetu
kotetuco
0
170
エンジニアと一緒にテストコードの設計と実装を改善した話
mototakatsu
0
260
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
840
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
320
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
520
AWS CDK を「作」ってみた 〜フルスクラッチで見えた CDK の裏側〜 / aws-cdk-from-scratch
gotok365
3
170
これからAgentCoreを触る方へトレンドはGatewayです
har1101
6
490
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
240
20260623_Loop Engineeringで自分の分身の問い合わせBotを作る
ryugen04
0
210
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
840
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
120
Featured
See All Featured
The Pragmatic Product Professional
lauravandoore
37
7.4k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
260
Building the Perfect Custom Keyboard
takai
2
810
The World Runs on Bad Software
bkeepers
PRO
72
12k
BBQ
matthewcrist
89
10k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
750
Faster Mobile Websites
deanohume
310
32k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.6k
Accessibility Awareness
sabderemane
1
150
Marketing to machines
jonoalderson
1
5.6k
Done Done
chrislema
186
16k
Technical Leadership for Architectural Decision Making
baasie
3
440
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でコンパイルするため、複数の画像処理を組み合わせた際 には職人芸コードの組み合わせよりも高速なコードが生成される可能性がある