Spaces:
Sleeping
Sleeping
umyuu
commited on
Commit
•
8ccf878
1
Parent(s):
232a35a
flake8
Browse files- .vscode/extensions.json +5 -0
- .vscode/settings.json +16 -0
- app.py +16 -17
- src/myapp.py +82 -60
- src/reporter.py +15 -7
- src/saliency.py +19 -18
- src/utils.py +26 -8
- test/test_create_grayscale_gradation.py +9 -1
.vscode/extensions.json
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"recommendations": [
|
3 |
+
"ms-python.flake8"
|
4 |
+
]
|
5 |
+
}
|
.vscode/settings.json
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cSpell.words": [
|
3 |
+
"astype",
|
4 |
+
"dtype",
|
5 |
+
"fromarray",
|
6 |
+
"Gradio",
|
7 |
+
"inbrowser",
|
8 |
+
"ndarray"
|
9 |
+
],
|
10 |
+
"python.analysis.typeCheckingMode": "basic",
|
11 |
+
"flake8.args": [
|
12 |
+
"--ignore=E265,W291",
|
13 |
+
"--max-complexity=10",
|
14 |
+
"--max-line-length=127"
|
15 |
+
]
|
16 |
+
}
|
app.py
CHANGED
@@ -4,11 +4,12 @@
|
|
4 |
"""
|
5 |
from argparse import ArgumentParser, BooleanOptionalAction
|
6 |
|
7 |
-
|
8 |
-
from src.
|
9 |
-
|
10 |
PROGRAM_NAME = 'SaliencyMapDemo'
|
11 |
-
__version__ =
|
|
|
12 |
|
13 |
def main():
|
14 |
"""
|
@@ -16,22 +17,20 @@ def main():
|
|
16 |
1, コマンドライン引数の解析を行います
|
17 |
2, アプリを起動します。
|
18 |
"""
|
19 |
-
log = get_current_reporter()
|
20 |
-
log.info("#アプリ起動中")
|
21 |
-
watch = utils.Stopwatch.startNew()
|
22 |
-
|
23 |
-
from src.myapp import runApp
|
24 |
-
|
25 |
parser = ArgumentParser(prog=PROGRAM_NAME, description="SaliencyMapDemo")
|
26 |
-
parser.add_argument('--
|
27 |
-
|
28 |
-
parser.add_argument('--
|
29 |
-
|
|
|
|
|
|
|
|
|
30 |
parser.add_argument('--version', action='version', version=f'%(prog)s {__version__}')
|
31 |
-
|
32 |
args = parser.parse_args()
|
33 |
-
|
34 |
-
|
35 |
|
36 |
if __name__ == "__main__":
|
37 |
main()
|
|
|
4 |
"""
|
5 |
from argparse import ArgumentParser, BooleanOptionalAction
|
6 |
|
7 |
+
from src.utils import get_package_version
|
8 |
+
from src.myapp import run_app
|
9 |
+
|
10 |
PROGRAM_NAME = 'SaliencyMapDemo'
|
11 |
+
__version__ = get_package_version()
|
12 |
+
|
13 |
|
14 |
def main():
|
15 |
"""
|
|
|
17 |
1, コマンドライン引数の解析を行います
|
18 |
2, アプリを起動します。
|
19 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
parser = ArgumentParser(prog=PROGRAM_NAME, description="SaliencyMapDemo")
|
21 |
+
parser.add_argument('--inbrowser',
|
22 |
+
action=BooleanOptionalAction, default=True, help="Gradio inbrowser")
|
23 |
+
parser.add_argument('--share',
|
24 |
+
action=BooleanOptionalAction, default=False, help="Gradio share")
|
25 |
+
parser.add_argument('--server_port',
|
26 |
+
type=int, default=7860, help="Gradio server port")
|
27 |
+
parser.add_argument('--max_file_size',
|
28 |
+
type=str, default="20MB", help="Gradio max file size")
|
29 |
parser.add_argument('--version', action='version', version=f'%(prog)s {__version__}')
|
30 |
+
|
31 |
args = parser.parse_args()
|
32 |
+
run_app(args)
|
33 |
+
|
34 |
|
35 |
if __name__ == "__main__":
|
36 |
main()
|
src/myapp.py
CHANGED
@@ -1,40 +1,54 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
|
|
2 |
from typing import Literal
|
3 |
|
4 |
import argparse
|
5 |
-
from datetime import datetime
|
6 |
import sys
|
7 |
|
8 |
import gradio as gr
|
9 |
import numpy as np
|
10 |
|
11 |
-
|
12 |
-
from src.saliency import SaliencyMap,
|
13 |
from src.reporter import get_current_reporter
|
14 |
|
15 |
PROGRAM_NAME = 'SaliencyMapDemo'
|
16 |
-
__version__ =
|
17 |
log = get_current_reporter()
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
#print(f"{datetime.now()}#jet")
|
21 |
saliency = SaliencyMap("SpectralResidual")
|
22 |
-
success,
|
23 |
-
|
|
|
|
|
24 |
#print(f"{datetime.now()}#jet")
|
25 |
-
|
26 |
return retval
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
29 |
#print(f"{datetime.now()}#hot")
|
30 |
saliency = SaliencyMap("SpectralResidual")
|
31 |
-
success,
|
32 |
-
|
|
|
|
|
33 |
#print(f"{datetime.now()}#hot")
|
34 |
-
|
35 |
return retval
|
36 |
|
37 |
-
|
|
|
38 |
"""
|
39 |
入力画像を元に顕著マップを計算します。
|
40 |
|
@@ -46,27 +60,26 @@ def submit_Clicked(image: np.ndarray, algorithm: str):
|
|
46 |
np.ndarray: HOT画像
|
47 |
"""
|
48 |
#log.info(f"#submit_Clicked")
|
49 |
-
watch = utils.Stopwatch.startNew()
|
50 |
-
|
51 |
saliency = SaliencyMap(algorithm)
|
52 |
-
success,
|
53 |
-
#log.info(f"#SaliencyMap
|
54 |
|
55 |
if not success:
|
56 |
-
return image, image
|
57 |
-
|
58 |
-
#log.info(f"#jet")
|
59 |
-
jet =
|
60 |
-
#jet = None
|
61 |
-
#log.info(f"#hot")
|
62 |
-
hot =
|
63 |
-
|
64 |
saliency = None
|
65 |
#log.info(f"#submit_Clicked End{watch.stop():.3f}")
|
66 |
-
|
67 |
return jet, hot
|
68 |
|
69 |
-
|
|
|
70 |
"""
|
71 |
アプリの画面を作成し、Gradioサービスを起動します。
|
72 |
|
@@ -76,59 +89,68 @@ def runApp(args: argparse.Namespace, watch: utils.Stopwatch) -> None:
|
|
76 |
"""
|
77 |
# analytics_enabled=False
|
78 |
# https://github.com/gradio-app/gradio/issues/4226
|
79 |
-
with gr.Blocks(
|
80 |
-
|
|
|
81 |
head="""
|
82 |
<meta name="format-detection" content="telephone=no">
|
83 |
<meta name="robots" content="noindex, nofollow, noarchive">
|
84 |
<meta name="referrer" content="no-referrer" />
|
85 |
-
""") as demo:
|
86 |
-
|
87 |
-
gr.Markdown(
|
88 |
"""
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
91 |
with gr.Accordion("取り扱い説明書", open=False):
|
92 |
-
gr.Markdown(
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
3. 結果は、JETタブとHOTタブに表示します。
|
98 |
""")
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
|
101 |
|
102 |
submit_button = gr.Button("submit", variant="primary")
|
103 |
|
104 |
with gr.Row():
|
105 |
with gr.Tab("input", id="input"):
|
106 |
|
107 |
-
image_input = gr.Image(sources
|
|
|
108 |
with gr.Tab("overlay(JET)"):
|
109 |
image_overlay_jet = gr.Image(interactive=False)
|
110 |
-
#tab_jet.select(jetTab_Selected, inputs=[image_input], outputs=image_overlay_jet)
|
111 |
with gr.Tab("overlay(HOT)"):
|
112 |
image_overlay_hot = gr.Image(interactive=False)
|
113 |
-
#tab_hot.select(hotTab_Selected,
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
""")
|
122 |
-
|
123 |
demo.queue(default_concurrency_limit=5)
|
124 |
-
|
125 |
log.info(f"#アプリ起動完了({watch.stop():.3f}s)")
|
126 |
# https://www.gradio.app/docs/gradio/blocks#blocks-launch
|
127 |
-
|
128 |
demo.launch(
|
129 |
-
max_file_size=args.max_file_size,
|
130 |
-
server_port=args.server_port,
|
131 |
inbrowser=args.inbrowser,
|
132 |
share=args.share,
|
|
|
|
|
133 |
)
|
134 |
-
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
+
"""myapp Widget"""
|
3 |
from typing import Literal
|
4 |
|
5 |
import argparse
|
6 |
+
#from datetime import datetime
|
7 |
import sys
|
8 |
|
9 |
import gradio as gr
|
10 |
import numpy as np
|
11 |
|
12 |
+
from src.utils import Stopwatch, get_package_version
|
13 |
+
from src.saliency import SaliencyMap, convert_colormap
|
14 |
from src.reporter import get_current_reporter
|
15 |
|
16 |
PROGRAM_NAME = 'SaliencyMapDemo'
|
17 |
+
__version__ = get_package_version()
|
18 |
log = get_current_reporter()
|
19 |
+
log.info("#アプリ起動中")
|
20 |
+
watch = Stopwatch.start_new()
|
21 |
+
|
22 |
+
|
23 |
+
def jettab_selected(image: np.ndarray):
|
24 |
+
"""
|
25 |
+
JETタブを選択時
|
26 |
+
"""
|
27 |
#print(f"{datetime.now()}#jet")
|
28 |
saliency = SaliencyMap("SpectralResidual")
|
29 |
+
success, saliency_map = saliency.compute(image)
|
30 |
+
if not success:
|
31 |
+
return image # エラーが発生した場合は入力画像を返します。
|
32 |
+
retval = convert_colormap(image, saliency_map, "jet")
|
33 |
#print(f"{datetime.now()}#jet")
|
|
|
34 |
return retval
|
35 |
+
|
36 |
+
|
37 |
+
def hottab_selected(image: np.ndarray):
|
38 |
+
"""
|
39 |
+
HOTタブを選択時
|
40 |
+
"""
|
41 |
#print(f"{datetime.now()}#hot")
|
42 |
saliency = SaliencyMap("SpectralResidual")
|
43 |
+
success, saliency_map = saliency.compute(image)
|
44 |
+
if not success:
|
45 |
+
return image # エラーが発生した場合は入力画像を返します。
|
46 |
+
retval = convert_colormap(image, saliency_map, "turbo")
|
47 |
#print(f"{datetime.now()}#hot")
|
|
|
48 |
return retval
|
49 |
|
50 |
+
|
51 |
+
def submit_clicked(image: np.ndarray, algorithm: Literal["SpectralResidual", "FineGrained"]):
|
52 |
"""
|
53 |
入力画像を元に顕著マップを計算します。
|
54 |
|
|
|
60 |
np.ndarray: HOT画像
|
61 |
"""
|
62 |
#log.info(f"#submit_Clicked")
|
63 |
+
#watch = utils.Stopwatch.startNew()
|
64 |
+
#
|
65 |
saliency = SaliencyMap(algorithm)
|
66 |
+
success, saliency_map = saliency.compute(image)
|
67 |
+
# log.info(f"#SaliencyMap compute()")
|
68 |
|
69 |
if not success:
|
70 |
+
return image, image # エラーが発生した場合は入力画像を返します。
|
71 |
+
|
72 |
+
# log.info(f"#jet")
|
73 |
+
jet = convert_colormap(image, saliency_map, "jet")
|
74 |
+
# jet = None
|
75 |
+
# log.info(f"#hot")
|
76 |
+
hot = convert_colormap(image, saliency_map, "hot")
|
|
|
77 |
saliency = None
|
78 |
#log.info(f"#submit_Clicked End{watch.stop():.3f}")
|
|
|
79 |
return jet, hot
|
80 |
|
81 |
+
|
82 |
+
def run_app(args: argparse.Namespace) -> None:
|
83 |
"""
|
84 |
アプリの画面を作成し、Gradioサービスを起動します。
|
85 |
|
|
|
89 |
"""
|
90 |
# analytics_enabled=False
|
91 |
# https://github.com/gradio-app/gradio/issues/4226
|
92 |
+
with gr.Blocks(
|
93 |
+
analytics_enabled=False,
|
94 |
+
title=f"{PROGRAM_NAME} {__version__}",
|
95 |
head="""
|
96 |
<meta name="format-detection" content="telephone=no">
|
97 |
<meta name="robots" content="noindex, nofollow, noarchive">
|
98 |
<meta name="referrer" content="no-referrer" />
|
|
|
|
|
|
|
99 |
"""
|
100 |
+
) as demo:
|
101 |
+
|
102 |
+
gr.Markdown("""
|
103 |
+
# Saliency Map demo.
|
104 |
+
""")
|
105 |
with gr.Accordion("取り扱い説明書", open=False):
|
106 |
+
gr.Markdown("""
|
107 |
+
1. inputタブで画像を選択します。
|
108 |
+
2. Submitボタンを押します。
|
109 |
+
※画像は外部送信していません。ローカルで処理が完結します。
|
110 |
+
3. 結果は、JETタブとHOTタブに表示します。
|
|
|
111 |
""")
|
112 |
+
algorithm_type = gr.Radio(
|
113 |
+
["SpectralResidual", "FineGrained"],
|
114 |
+
label="Saliency",
|
115 |
+
value="SpectralResidual",
|
116 |
+
interactive=True
|
117 |
+
)
|
118 |
|
119 |
submit_button = gr.Button("submit", variant="primary")
|
120 |
|
121 |
with gr.Row():
|
122 |
with gr.Tab("input", id="input"):
|
123 |
|
124 |
+
image_input = gr.Image(sources=["upload", "clipboard"],
|
125 |
+
interactive=True)
|
126 |
with gr.Tab("overlay(JET)"):
|
127 |
image_overlay_jet = gr.Image(interactive=False)
|
128 |
+
# tab_jet.select(jetTab_Selected, inputs=[image_input], outputs=image_overlay_jet)
|
129 |
with gr.Tab("overlay(HOT)"):
|
130 |
image_overlay_hot = gr.Image(interactive=False)
|
131 |
+
# tab_hot.select(hotTab_Selected,
|
132 |
+
# inputs=[image_input],
|
133 |
+
# outputs=image_overlay_hot, api_name=False)
|
134 |
+
#
|
135 |
+
submit_button.click(
|
136 |
+
submit_clicked,
|
137 |
+
inputs=[image_input, algorithm_type],
|
138 |
+
outputs=[image_overlay_jet,
|
139 |
+
image_overlay_hot]
|
140 |
+
)
|
141 |
+
|
142 |
+
gr.Markdown(f"""
|
143 |
+
Python {sys.version}
|
144 |
+
App {__version__}
|
145 |
""")
|
146 |
+
|
147 |
demo.queue(default_concurrency_limit=5)
|
148 |
+
|
149 |
log.info(f"#アプリ起動完了({watch.stop():.3f}s)")
|
150 |
# https://www.gradio.app/docs/gradio/blocks#blocks-launch
|
|
|
151 |
demo.launch(
|
|
|
|
|
152 |
inbrowser=args.inbrowser,
|
153 |
share=args.share,
|
154 |
+
server_port=args.server_port,
|
155 |
+
max_file_size=args.max_file_size,
|
156 |
)
|
|
src/reporter.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
ログハンドラーが重複登録されるのを防ぐために1箇所で生成してログハンドラーを返します。
|
5 |
Example:
|
6 |
from reporter import get_current_reporter
|
7 |
-
|
8 |
logger = get_current_reporter()
|
9 |
logger.info("message");
|
10 |
"""
|
@@ -13,37 +13,45 @@ from logging import DEBUG
|
|
13 |
|
14 |
_reporters = []
|
15 |
|
|
|
16 |
def get_current_reporter() -> Logger:
|
|
|
|
|
|
|
17 |
return _reporters[-1]
|
18 |
|
19 |
-
|
|
|
20 |
"""
|
21 |
ログハンドラーを生成します。
|
22 |
-
@see https://docs.python.jp/3/howto/logging-cookbook.html
|
23 |
-
|
24 |
Parameters:
|
25 |
name: アプリ名
|
26 |
"""
|
27 |
-
handler = StreamHandler()
|
28 |
formatter = Formatter('%(asctime)s%(message)s')
|
29 |
handler.setFormatter(formatter)
|
30 |
handler.setLevel(DEBUG)
|
31 |
-
|
32 |
logger = getLogger(name)
|
33 |
logger.setLevel(DEBUG)
|
34 |
logger.addHandler(handler)
|
35 |
_reporters.append(logger)
|
36 |
|
|
|
37 |
__make_reporter()
|
38 |
|
|
|
39 |
def main():
|
40 |
"""
|
41 |
Entry Point
|
42 |
"""
|
43 |
assert len(_reporters) == 1
|
44 |
-
|
45 |
logger = get_current_reporter()
|
46 |
logger.debug("main")
|
47 |
|
|
|
48 |
if __name__ == "__main__":
|
49 |
main()
|
|
|
4 |
ログハンドラーが重複登録されるのを防ぐために1箇所で生成してログハンドラーを返します。
|
5 |
Example:
|
6 |
from reporter import get_current_reporter
|
7 |
+
|
8 |
logger = get_current_reporter()
|
9 |
logger.info("message");
|
10 |
"""
|
|
|
13 |
|
14 |
_reporters = []
|
15 |
|
16 |
+
|
17 |
def get_current_reporter() -> Logger:
|
18 |
+
"""
|
19 |
+
シングルトン
|
20 |
+
"""
|
21 |
return _reporters[-1]
|
22 |
|
23 |
+
|
24 |
+
def __make_reporter(name: str = 'SaliencyMapDemo') -> None:
|
25 |
"""
|
26 |
ログハンドラーを生成します。
|
27 |
+
@see https://docs.python.jp/3/howto/logging-cookbook.html
|
28 |
+
|
29 |
Parameters:
|
30 |
name: アプリ名
|
31 |
"""
|
32 |
+
handler = StreamHandler() # コンソールに出力します。
|
33 |
formatter = Formatter('%(asctime)s%(message)s')
|
34 |
handler.setFormatter(formatter)
|
35 |
handler.setLevel(DEBUG)
|
36 |
+
|
37 |
logger = getLogger(name)
|
38 |
logger.setLevel(DEBUG)
|
39 |
logger.addHandler(handler)
|
40 |
_reporters.append(logger)
|
41 |
|
42 |
+
|
43 |
__make_reporter()
|
44 |
|
45 |
+
|
46 |
def main():
|
47 |
"""
|
48 |
Entry Point
|
49 |
"""
|
50 |
assert len(_reporters) == 1
|
51 |
+
|
52 |
logger = get_current_reporter()
|
53 |
logger.debug("main")
|
54 |
|
55 |
+
|
56 |
if __name__ == "__main__":
|
57 |
main()
|
src/saliency.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
-
|
|
|
3 |
|
4 |
import numpy as np
|
5 |
import cv2
|
@@ -10,23 +11,22 @@ class SaliencyMap:
|
|
10 |
SaliencyMap 顕著性マップを計算するクラスです。
|
11 |
Example:
|
12 |
from lib.saliency import SaliencyMap
|
13 |
-
|
14 |
saliency = SaliencyMap("SpectralResidual")
|
15 |
-
success, saliencyMap = saliency.
|
16 |
"""
|
17 |
def __init__(
|
18 |
self,
|
19 |
algorithm: Literal["SpectralResidual", "FineGrained"] = "SpectralResidual",
|
20 |
-
|
21 |
self.algorithm = algorithm
|
22 |
# OpenCVのsaliencyを作成します。
|
23 |
if algorithm == "SpectralResidual":
|
24 |
self.saliency = cv2.saliency.StaticSaliencySpectralResidual_create()
|
25 |
else:
|
26 |
self.saliency = cv2.saliency.StaticSaliencyFineGrained_create()
|
27 |
-
|
28 |
|
29 |
-
def
|
30 |
"""
|
31 |
入力画像から顕著性マップを作成します。
|
32 |
|
@@ -41,31 +41,32 @@ class SaliencyMap:
|
|
41 |
# 画像の顕著性を計算します。
|
42 |
return self.saliency.computeSaliency(image)
|
43 |
|
44 |
-
|
|
|
45 |
image: np.ndarray,
|
46 |
-
|
47 |
-
colormap_name: Literal["jet", "hot", "turbo"] = "jet"
|
|
|
48 |
"""
|
49 |
顕著性マップをカラーマップに変換後に、入力画像に重ね合わせします。
|
50 |
-
|
51 |
Parameters:
|
52 |
image: 入力画像
|
53 |
-
|
54 |
colormap_name: カラーマップの種類
|
55 |
|
56 |
Returns:
|
57 |
np.ndarray: 重ね合わせた画像(RGBA形式)
|
58 |
"""
|
59 |
-
|
60 |
-
if colormap_name not in
|
61 |
-
raise ValueError(colormap_name)
|
62 |
|
63 |
# 顕著性マップをカラーマップに変換
|
64 |
-
|
65 |
-
|
66 |
#return saliencyMap
|
67 |
# 入力画像とカラーマップを重ね合わせ
|
68 |
-
overlay = cv2.addWeighted(image, 0.5,
|
69 |
#return overlay
|
70 |
-
|
71 |
return cv2.cvtColor(overlay, cv2.COLOR_BGR2RGBA)
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
+
"""SaliencyMapを計算する"""
|
3 |
+
from typing import Any, Tuple, Literal
|
4 |
|
5 |
import numpy as np
|
6 |
import cv2
|
|
|
11 |
SaliencyMap 顕著性マップを計算するクラスです。
|
12 |
Example:
|
13 |
from lib.saliency import SaliencyMap
|
14 |
+
|
15 |
saliency = SaliencyMap("SpectralResidual")
|
16 |
+
success, saliencyMap = saliency.compute(image)
|
17 |
"""
|
18 |
def __init__(
|
19 |
self,
|
20 |
algorithm: Literal["SpectralResidual", "FineGrained"] = "SpectralResidual",
|
21 |
+
):
|
22 |
self.algorithm = algorithm
|
23 |
# OpenCVのsaliencyを作成します。
|
24 |
if algorithm == "SpectralResidual":
|
25 |
self.saliency = cv2.saliency.StaticSaliencySpectralResidual_create()
|
26 |
else:
|
27 |
self.saliency = cv2.saliency.StaticSaliencyFineGrained_create()
|
|
|
28 |
|
29 |
+
def compute(self, image: np.ndarray) -> Tuple[bool, Any]:
|
30 |
"""
|
31 |
入力画像から顕著性マップを作成します。
|
32 |
|
|
|
41 |
# 画像の顕著性を計算します。
|
42 |
return self.saliency.computeSaliency(image)
|
43 |
|
44 |
+
|
45 |
+
def convert_colormap(
|
46 |
image: np.ndarray,
|
47 |
+
saliency_map: np.ndarray,
|
48 |
+
colormap_name: Literal["jet", "hot", "turbo"] = "jet"
|
49 |
+
):
|
50 |
"""
|
51 |
顕著性マップをカラーマップに変換後に、入力画像に重ね合わせします。
|
52 |
+
|
53 |
Parameters:
|
54 |
image: 入力画像
|
55 |
+
saliency_map: 顕著性マップ
|
56 |
colormap_name: カラーマップの種類
|
57 |
|
58 |
Returns:
|
59 |
np.ndarray: 重ね合わせた画像(RGBA形式)
|
60 |
"""
|
61 |
+
maps = {"jet": cv2.COLORMAP_JET, "hot": cv2.COLORMAP_HOT, "turbo": cv2.COLORMAP_TURBO}
|
62 |
+
if colormap_name not in maps:
|
63 |
+
raise ValueError(colormap_name)
|
64 |
|
65 |
# 顕著性マップをカラーマップに変換
|
66 |
+
saliency_map = (saliency_map * 255).astype("uint8")
|
67 |
+
saliency_map = cv2.applyColorMap(saliency_map, maps[colormap_name])
|
68 |
#return saliencyMap
|
69 |
# 入力画像とカラーマップを重ね合わせ
|
70 |
+
overlay = cv2.addWeighted(image, 0.5, saliency_map, 0.5, 0)
|
71 |
#return overlay
|
|
|
72 |
return cv2.cvtColor(overlay, cv2.COLOR_BGR2RGBA)
|
src/utils.py
CHANGED
@@ -1,39 +1,57 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
|
|
2 |
import time
|
3 |
|
|
|
4 |
def get_package_version() -> str:
|
|
|
|
|
|
|
5 |
return '0.0.4'
|
6 |
|
|
|
7 |
class Stopwatch:
|
8 |
"""
|
9 |
Stopwatch 経過時間を計測するためのクラスです。
|
10 |
Example:
|
11 |
-
from utils import Stopwatch
|
12 |
-
|
13 |
-
watch = Stopwatch.
|
14 |
# 計測する処理
|
15 |
print(f"{watch.stop():.3f}")
|
16 |
"""
|
17 |
|
18 |
def __init__(self):
|
19 |
-
self._start_time =
|
20 |
-
self._elapsed = 0
|
21 |
|
22 |
@property
|
23 |
-
def
|
|
|
|
|
|
|
24 |
return self._elapsed
|
25 |
|
26 |
def start(self) -> None:
|
|
|
|
|
|
|
27 |
self._start_time = time.perf_counter()
|
28 |
-
self._elapsed = 0
|
29 |
|
30 |
@classmethod
|
31 |
-
def
|
|
|
|
|
|
|
32 |
stopwatch = Stopwatch()
|
33 |
stopwatch.start()
|
34 |
return stopwatch
|
35 |
|
36 |
def stop(self):
|
|
|
|
|
|
|
37 |
end_time = time.perf_counter()
|
38 |
self._elapsed = end_time - self._start_time
|
39 |
return self._elapsed
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
+
"""ユーティリティ"""
|
3 |
import time
|
4 |
|
5 |
+
|
6 |
def get_package_version() -> str:
|
7 |
+
"""
|
8 |
+
バージョン情報
|
9 |
+
"""
|
10 |
return '0.0.4'
|
11 |
|
12 |
+
|
13 |
class Stopwatch:
|
14 |
"""
|
15 |
Stopwatch 経過時間を計測するためのクラスです。
|
16 |
Example:
|
17 |
+
from src.utils import Stopwatch
|
18 |
+
|
19 |
+
watch = Stopwatch.start_new()
|
20 |
# 計測する処理
|
21 |
print(f"{watch.stop():.3f}")
|
22 |
"""
|
23 |
|
24 |
def __init__(self):
|
25 |
+
self._start_time = 0
|
26 |
+
self._elapsed = 0
|
27 |
|
28 |
@property
|
29 |
+
def elapsed(self):
|
30 |
+
"""
|
31 |
+
経過時間
|
32 |
+
"""
|
33 |
return self._elapsed
|
34 |
|
35 |
def start(self) -> None:
|
36 |
+
"""
|
37 |
+
計測を開始します。
|
38 |
+
"""
|
39 |
self._start_time = time.perf_counter()
|
40 |
+
self._elapsed = 0
|
41 |
|
42 |
@classmethod
|
43 |
+
def start_new(cls):
|
44 |
+
"""
|
45 |
+
ストップウォッチを生成し計測を開始します。
|
46 |
+
"""
|
47 |
stopwatch = Stopwatch()
|
48 |
stopwatch.start()
|
49 |
return stopwatch
|
50 |
|
51 |
def stop(self):
|
52 |
+
"""
|
53 |
+
計測を終了します。
|
54 |
+
"""
|
55 |
end_time = time.perf_counter()
|
56 |
self._elapsed = end_time - self._start_time
|
57 |
return self._elapsed
|
test/test_create_grayscale_gradation.py
CHANGED
@@ -1,14 +1,21 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
|
|
2 |
import unittest
|
3 |
|
4 |
import numpy as np
|
5 |
from PIL import Image
|
6 |
|
|
|
7 |
class TestGrayscale(unittest.TestCase):
|
8 |
-
|
|
|
|
|
9 |
|
10 |
|
11 |
def main():
|
|
|
|
|
|
|
12 |
# グラデーションのサイズを定義します
|
13 |
width = 256
|
14 |
height = 256
|
@@ -25,6 +32,7 @@ def main():
|
|
25 |
# 画像を表示します
|
26 |
image.show()
|
27 |
|
|
|
28 |
if __name__ == "__main__":
|
29 |
#main()
|
30 |
unittest.main()
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
+
"""単体テストモジュール"""
|
3 |
import unittest
|
4 |
|
5 |
import numpy as np
|
6 |
from PIL import Image
|
7 |
|
8 |
+
|
9 |
class TestGrayscale(unittest.TestCase):
|
10 |
+
"""
|
11 |
+
グレースケールのテスト
|
12 |
+
"""
|
13 |
|
14 |
|
15 |
def main():
|
16 |
+
"""
|
17 |
+
単体テストのエントリーポイント
|
18 |
+
"""
|
19 |
# グラデーションのサイズを定義します
|
20 |
width = 256
|
21 |
height = 256
|
|
|
32 |
# 画像を表示します
|
33 |
image.show()
|
34 |
|
35 |
+
|
36 |
if __name__ == "__main__":
|
37 |
#main()
|
38 |
unittest.main()
|