Spaces:
Sleeping
Sleeping
Merge pull request #2 from umyuu/feature/0.0.2
Browse files- README.md +40 -25
- ThirdPartyNotices.txt +18 -0
- run.bat +1 -1
- src/app.py +50 -22
- src/launch.py +28 -0
- src/utils.py +34 -0
README.md
CHANGED
@@ -1,26 +1,41 @@
|
|
1 |
-
#
|
2 |
-
##
|
3 |
-
|
4 |
-
私は画像処理についてはまだ初心者ですが、興味を持っています。
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
[MIT License](LICENSE)
|
|
|
1 |
+
# SaliencyMap
|
2 |
+
## 概要
|
3 |
+
顕著性マップを表示するデモアプリです。
|
4 |
+
私は画像処理についてはまだ初心者ですが、興味を持っています。
|
5 |
+
> **技術的なお話**
|
6 |
+
> opencv-contribパッケージの`cv2.saliency.StaticSaliencySpectralResidual`を呼び出すラッパーアプリです。
|
7 |
+
|
8 |
+
## 導入方法
|
9 |
+
### 1. セットアップ
|
10 |
+
- 以下のファイルをダブルクリックします。
|
11 |
+
~~~
|
12 |
+
01-installation.bat
|
13 |
+
~~~
|
14 |
+
### 2. 実行
|
15 |
+
1. 以下のファイルをダブルクリックします。
|
16 |
+
~~~
|
17 |
+
run.bat
|
18 |
+
~~~
|
19 |
+
2. 実行するとブラウザが起動し[http://127.0.0.1:9999](http://127.0.0.1:9999)を開きます。
|
20 |
+
> **NOTE**
|
21 |
+
> デフォルトポート番号は、9999です。
|
22 |
+
> アプリが起動せずポート番号を変更する時は、メモ帳で`run.bat`を開きの以下行の9999を別の数字(8888)などに変更し保存してください。
|
23 |
+
> python src\launch.py --server_port 9999
|
24 |
+
> REM 変更後
|
25 |
+
> python src\launch.py --server_port 8888
|
26 |
+
|
27 |
+
## 補足事項
|
28 |
+
- ローカルで処理が完結します。画像を外部には送信しません。
|
29 |
+
|
30 |
+
## Uninstall
|
31 |
+
このアプリをアンインストールするには、以下の手順に従ってください。
|
32 |
+
- アプリのフォルダをフォルダ毎削除してください。
|
33 |
+
- アプリで処理した画像ファイルが一時フォルダに残ります。不要な場合は削除をお願いします。
|
34 |
+
- 一時フォルダの場所
|
35 |
+
パソコンの画面左下の「検索するには、ここに入力します」に以下をコピペしてEnterを押します。
|
36 |
+
~~~
|
37 |
+
C:\Users\%USERNAME%\AppData\Local\Temp\gradio
|
38 |
+
~~~
|
39 |
+
|
40 |
+
## Source code License.
|
41 |
[MIT License](LICENSE)
|
ThirdPartyNotices.txt
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
NOTICES
|
2 |
+
|
3 |
+
This repository uses the materials listed or described below.
|
4 |
+
|
5 |
+
---------------------------------------------------------
|
6 |
+
|
7 |
+
Gradio - Apache-2.0
|
8 |
+
https://github.com/gradio-app/gradio
|
9 |
+
---------------------------------------------------------
|
10 |
+
|
11 |
+
---------------------------------------------------------
|
12 |
+
|
13 |
+
opencv-python - MIT
|
14 |
+
https://github.com/opencv/opencv-python
|
15 |
+
|
16 |
+
LICENSE-3RD-PARTY.txt
|
17 |
+
https://github.com/opencv/opencv-python/blob/master/LICENSE-3RD-PARTY.txt
|
18 |
+
---------------------------------------------------------
|
run.bat
CHANGED
@@ -2,6 +2,6 @@
|
|
2 |
|
3 |
cd %~dp0
|
4 |
call venv\Scripts\activate
|
5 |
-
python src\
|
6 |
|
7 |
TIMEOUT /T 10
|
|
|
2 |
|
3 |
cd %~dp0
|
4 |
call venv\Scripts\activate
|
5 |
+
python src\launch.py --server_port 9999
|
6 |
|
7 |
TIMEOUT /T 10
|
src/app.py
CHANGED
@@ -3,15 +3,31 @@
|
|
3 |
SaliencyMapDemo
|
4 |
"""
|
5 |
import argparse
|
|
|
|
|
|
|
6 |
import cv2
|
7 |
import gradio as gr
|
8 |
import numpy as np
|
9 |
-
|
|
|
10 |
|
11 |
PROGRAM_NAME = 'SaliencyMapDemo'
|
12 |
-
__version__ =
|
13 |
|
14 |
def compute_saliency(image: np.ndarray):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
# OpenCVのsaliencyを作成
|
16 |
saliency = cv2.saliency.StaticSaliencySpectralResidual_create()
|
17 |
# 画像の顕著性を計算
|
@@ -21,23 +37,41 @@ def compute_saliency(image: np.ndarray):
|
|
21 |
# 顕著性マップをカラーマップに変換
|
22 |
saliencyMap = (saliencyMap * 255).astype("uint8")
|
23 |
saliencyMap = cv2.applyColorMap(saliencyMap, cv2.COLORMAP_JET)
|
|
|
|
|
24 |
# 元の画像とカラーマップを重ね合わせ
|
25 |
overlay = cv2.addWeighted(image, 0.5, saliencyMap, 0.5, 0)
|
|
|
26 |
return overlay
|
27 |
else:
|
28 |
return image # エラーが発生した場合は元の画像を返す
|
29 |
|
30 |
-
def
|
31 |
"""
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
33 |
"""
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
gr.Markdown(
|
36 |
"""
|
37 |
# Saliency Map demo.
|
38 |
1. inputタブで画像を選択します。
|
39 |
-
2. Submit
|
40 |
-
|
|
|
41 |
""")
|
42 |
|
43 |
submit_button = gr.Button("submit")
|
@@ -46,26 +80,20 @@ def main(args):
|
|
46 |
with gr.Tab("input"):
|
47 |
image_input = gr.Image()
|
48 |
with gr.Tab("overlay"):
|
49 |
-
image_overlay = gr.Image()
|
50 |
|
51 |
|
52 |
submit_button.click(compute_saliency, inputs=image_input, outputs=image_overlay)
|
53 |
-
|
54 |
gr.Markdown(
|
55 |
f"""
|
56 |
Python {sys.version}
|
57 |
App {__version__}
|
58 |
""")
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
parser.add_argument('--server_port', type=int, default=9999, help="Gradio server port")
|
67 |
-
parser.add_argument('--max_file_size', type=int, default=20 * gr.FileSize.MB, help="Gradio max file size")
|
68 |
-
parser.add_argument('--version', action='version', version='%(prog)s {0}'.format(__version__))
|
69 |
-
|
70 |
-
main(parser.parse_args())
|
71 |
-
|
|
|
3 |
SaliencyMapDemo
|
4 |
"""
|
5 |
import argparse
|
6 |
+
from datetime import datetime
|
7 |
+
import sys
|
8 |
+
|
9 |
import cv2
|
10 |
import gradio as gr
|
11 |
import numpy as np
|
12 |
+
|
13 |
+
import utils
|
14 |
|
15 |
PROGRAM_NAME = 'SaliencyMapDemo'
|
16 |
+
__version__ = utils.get_package_version()
|
17 |
|
18 |
def compute_saliency(image: np.ndarray):
|
19 |
+
"""
|
20 |
+
入力画像から顕著性マップを作成しJET画像を返します。
|
21 |
+
Parameters
|
22 |
+
----------
|
23 |
+
param1 : np.ndarray
|
24 |
+
入力画像
|
25 |
+
|
26 |
+
Returns
|
27 |
+
-------
|
28 |
+
np.ndarray
|
29 |
+
カラーマップのJET画像
|
30 |
+
"""
|
31 |
# OpenCVのsaliencyを作成
|
32 |
saliency = cv2.saliency.StaticSaliencySpectralResidual_create()
|
33 |
# 画像の顕著性を計算
|
|
|
37 |
# 顕著性マップをカラーマップに変換
|
38 |
saliencyMap = (saliencyMap * 255).astype("uint8")
|
39 |
saliencyMap = cv2.applyColorMap(saliencyMap, cv2.COLORMAP_JET)
|
40 |
+
|
41 |
+
#overlay = saliencyMap
|
42 |
# 元の画像とカラーマップを重ね合わせ
|
43 |
overlay = cv2.addWeighted(image, 0.5, saliencyMap, 0.5, 0)
|
44 |
+
|
45 |
return overlay
|
46 |
else:
|
47 |
return image # エラーが発生した場合は元の画像を返す
|
48 |
|
49 |
+
def run(args: argparse.Namespace, watch: utils.Stopwatch) -> None:
|
50 |
"""
|
51 |
+
アプリの画面を作成し、Gradioサービスを起動します。
|
52 |
+
----------
|
53 |
+
param1 : argparse.Namespace
|
54 |
+
コマンドライン引数
|
55 |
+
param2 : utils.Stopwatch
|
56 |
+
起動したスタート時間
|
57 |
"""
|
58 |
+
# analytics_enabled=False
|
59 |
+
# https://github.com/gradio-app/gradio/issues/4226
|
60 |
+
with gr.Blocks(analytics_enabled=False, \
|
61 |
+
title=f"{PROGRAM_NAME} {__version__}", \
|
62 |
+
head="""
|
63 |
+
<meta name="format-detection" content="telephone=no">
|
64 |
+
<meta name="robots" content="noindex, nofollow, noarchive">
|
65 |
+
<meta name="referrer" content="no-referrer" />
|
66 |
+
""") as demo:
|
67 |
+
|
68 |
gr.Markdown(
|
69 |
"""
|
70 |
# Saliency Map demo.
|
71 |
1. inputタブで画像を選択します。
|
72 |
+
2. Submitボタンを押します。
|
73 |
+
※画像は外部送信していません。ローカルで処理が完結します。
|
74 |
+
3. 結果は、overlayタブに表示します。
|
75 |
""")
|
76 |
|
77 |
submit_button = gr.Button("submit")
|
|
|
80 |
with gr.Tab("input"):
|
81 |
image_input = gr.Image()
|
82 |
with gr.Tab("overlay"):
|
83 |
+
image_overlay = gr.Image(interactive=False)
|
84 |
|
85 |
|
86 |
submit_button.click(compute_saliency, inputs=image_input, outputs=image_overlay)
|
87 |
+
|
88 |
gr.Markdown(
|
89 |
f"""
|
90 |
Python {sys.version}
|
91 |
App {__version__}
|
92 |
""")
|
93 |
+
|
94 |
+
demo.queue(default_concurrency_limit=5)
|
95 |
+
|
96 |
+
print(f"{datetime.now()}:アプリ起動完了({watch.stop():.3f}s)")
|
97 |
+
|
98 |
+
# https://www.gradio.app/docs/gradio/blocks#blocks-launch
|
99 |
+
demo.launch(max_file_size=args.max_file_size, server_port=args.server_port, inbrowser=True, share=False)
|
|
|
|
|
|
|
|
|
|
|
|
src/launch.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""
|
3 |
+
SaliencyMapDemo
|
4 |
+
"""
|
5 |
+
import argparse
|
6 |
+
from datetime import datetime
|
7 |
+
|
8 |
+
from utils import get_package_version, Stopwatch
|
9 |
+
|
10 |
+
def main():
|
11 |
+
"""
|
12 |
+
エントリーポイント
|
13 |
+
コマンドライン引数の解析を行います
|
14 |
+
"""
|
15 |
+
print(f"{datetime.now()}:アプリ起動中")
|
16 |
+
watch = Stopwatch.startNew()
|
17 |
+
|
18 |
+
import app
|
19 |
+
|
20 |
+
parser = argparse.ArgumentParser(prog=app.PROGRAM_NAME, description="SaliencyMapDemo")
|
21 |
+
parser.add_argument('--server_port', type=int, default=9999, help="Gradio server port")
|
22 |
+
parser.add_argument('--max_file_size', type=int, default=20 * 1024 * 1024, help="Gradio max file size")
|
23 |
+
parser.add_argument('--version', action='version', version=f'%(prog)s {get_package_version()}')
|
24 |
+
|
25 |
+
app.run(parser.parse_args(), watch)
|
26 |
+
|
27 |
+
if __name__ == "__main__":
|
28 |
+
main()
|
src/utils.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
import time
|
3 |
+
|
4 |
+
def get_package_version() -> str:
|
5 |
+
return '0.0.2'
|
6 |
+
|
7 |
+
class Stopwatch:
|
8 |
+
"""
|
9 |
+
Stopwatch 経過時間を計測するためのクラスです。
|
10 |
+
"""
|
11 |
+
|
12 |
+
def __init__(self):
|
13 |
+
self._start_time = None
|
14 |
+
self._elapsed = 0;
|
15 |
+
|
16 |
+
@property
|
17 |
+
def Elapsed(self):
|
18 |
+
return self._elapsed
|
19 |
+
|
20 |
+
def start(self) -> None:
|
21 |
+
self._start_time = time.perf_counter()
|
22 |
+
self._elapsed = 0;
|
23 |
+
|
24 |
+
@classmethod
|
25 |
+
def startNew(cls):
|
26 |
+
stopwatch = Stopwatch()
|
27 |
+
stopwatch.start()
|
28 |
+
return stopwatch
|
29 |
+
|
30 |
+
def stop(self):
|
31 |
+
end_time = time.perf_counter()
|
32 |
+
self._elapsed = end_time - self._start_time
|
33 |
+
return self._elapsed
|
34 |
+
|