File size: 6,887 Bytes
fba74bb
 
 
 
be1d691
fba74bb
 
 
 
be1d691
fba74bb
 
 
 
 
 
 
 
be1d691
fba74bb
 
be1d691
 
 
 
 
 
 
fba74bb
be1d691
fba74bb
 
 
 
 
 
 
 
 
be1d691
 
 
 
fba74bb
 
 
 
be1d691
 
 
 
fba74bb
be1d691
fba74bb
be1d691
fba74bb
be1d691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fba74bb
 
 
be1d691
fba74bb
 
be1d691
 
fba74bb
 
 
be1d691
fba74bb
 
be1d691
 
 
 
 
 
 
 
fba74bb
be1d691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fba74bb
 
be1d691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fba74bb
 
 
 
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import cv2
import numpy as np
import gradio as gr

def hsv_filter(image, h_low=0, h_high=179, s_low=0, s_high=255, v_low=0, v_high=255):
    """
    對輸入的圖像應用 HSV 過濾
    
    Args:
        image: 輸入的圖像(來自上傳)
        h_low, h_high: Hue(色調)的最低和最高值
        s_low, s_high: Saturation(飽和度)的最低和最高值
        v_low, v_high: Value(亮度)的最低和最高值
    
    Returns:
        原始圖像、HSV 過濾遮罩和過濾後的結果
    """
    if image is None:
        # 如果沒有圖像,返回None
        return None, None, None
    
    # 將圖像轉換為BGR(如果它是RGB)
    if len(image.shape) == 3 and image.shape[2] == 3:
        # Gradio 使用 RGB,但 OpenCV 使用 BGR
        image_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
    else:
        image_bgr = image
    
    # 將圖像轉換為 HSV 色彩空間
    hsv = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2HSV)
    
    # 設置 HSV 過濾範圍
    lower = np.array([h_low, s_low, v_low])
    upper = np.array([h_high, s_high, v_high])
    
    # 建立遮罩
    mask = cv2.inRange(hsv, lower, upper)
    
    # 使用遮罩從原始圖像中提取物體
    result = cv2.bitwise_and(image_bgr, image_bgr, mask=mask)
    
    # 將結果轉換回 RGB 以在 Gradio 中顯示
    result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB)
    
    # 將遮罩轉換為 RGB 以便在 Gradio 中顯示
    mask_rgb = cv2.cvtColor(mask, cv2.COLOR_GRAY2RGB)
    
    # 確保原始圖像也是 RGB
    orig_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
    
    return orig_rgb, mask_rgb, result_rgb

def create_test_image():
    """
    創建一個測試圖像,包含不同顏色區塊,用於演示 HSV 過濾效果
    """
    # 創建一個白色背景
    test_image = np.ones((300, 400, 3), dtype=np.uint8) * 255
    
    # 添加不同顏色的區塊(BGR 格式)
    # 紅色區塊
    test_image[50:150, 50:150] = [0, 0, 255]  # BGR格式的紅色
    # 綠色區塊
    test_image[50:150, 200:300] = [0, 255, 0]  # BGR格式的綠色
    # 藍色區塊
    test_image[200:250, 50:350] = [255, 0, 0]  # BGR格式的藍色
    # 黃色區塊
    test_image[150:200, 150:200] = [0, 255, 255]  # BGR格式的黃色
    
    # 將BGR轉換為RGB格式
    test_image_rgb = cv2.cvtColor(test_image, cv2.COLOR_BGR2RGB)
    
    return test_image_rgb

def process_image(image, h_low, h_high, s_low, s_high, v_low, v_high):
    """
    處理圖像的主函數
    """
    if image is None:
        # 如果沒有上傳圖像,使用測試圖像
        image = create_test_image()
    
    return hsv_filter(image, h_low, h_high, s_low, s_high, v_low, v_high)

# 創建 Gradio 界面
with gr.Blocks(title="HSV 顏色過濾器") as demo:
    gr.Markdown("# HSV 顏色過濾器")
    gr.Markdown("上傳圖像或使用測試圖像,然後調整 HSV 值範圍進行顏色過濾")
    
    with gr.Row():
        # 圖像輸入區域
        with gr.Column(scale=1):
            gr.Markdown("### 輸入圖像")
            input_image = gr.Image(type="numpy", label="上傳圖像")
            test_btn = gr.Button("使用測試圖像")
        
        # HSV 滑桿控制區域
        with gr.Column(scale=1):
            gr.Markdown("### HSV 參數控制")
            with gr.Row():
                with gr.Column():
                    h_low = gr.Slider(0, 179, 0, step=1, label="H Low(色調最小值)")
                    h_high = gr.Slider(0, 179, 179, step=1, label="H High(色調最大值)")
                with gr.Column():
                    s_low = gr.Slider(0, 255, 0, step=1, label="S Low(飽和度最小值)")
                    s_high = gr.Slider(0, 255, 255, step=1, label="S High(飽和度最大值)")
                with gr.Column():
                    v_low = gr.Slider(0, 255, 0, step=1, label="V Low(亮度最小值)")
                    v_high = gr.Slider(0, 255, 255, step=1, label="V High(亮度最大值)")
            
            # 創建一些預設值按鈕
            gr.Markdown("### 常用顏色預設")
            with gr.Row():
                red_btn = gr.Button("紅色")
                green_btn = gr.Button("綠色")
                blue_btn = gr.Button("藍色")
                yellow_btn = gr.Button("黃色")
    
    # 結果顯示區域
    with gr.Row():
        original_output = gr.Image(type="numpy", label="原始圖像")
        mask_output = gr.Image(type="numpy", label="遮罩")
        result_output = gr.Image(type="numpy", label="過濾結果")
    
    # 設置事件處理
    # 測試圖像按鈕
    test_btn.click(
        fn=lambda: create_test_image(),
        inputs=[],
        outputs=[input_image]
    )
    
    # 處理圖像函數
    def process_and_update(*args):
        return process_image(*args)
    
    # 連接輸入和滑桿到處理函數
    inputs = [input_image, h_low, h_high, s_low, s_high, v_low, v_high]
    outputs = [original_output, mask_output, result_output]
    
    # 當圖像或任何滑桿變化時觸發處理函數
    input_image.change(process_and_update, inputs=inputs, outputs=outputs)
    
    for slider in [h_low, h_high, s_low, s_high, v_low, v_high]:
        slider.change(process_and_update, inputs=inputs, outputs=outputs)
    
    # 預設值按鈕
    # 紅色 (Hue: ~0-10 或 ~160-179)
    red_btn.click(
        fn=lambda: [None, 0, 10, 100, 255, 100, 255],
        inputs=[],
        outputs=[input_image, h_low, h_high, s_low, s_high, v_low, v_high]
    ).then(
        fn=process_and_update,
        inputs=inputs,
        outputs=outputs
    )
    
    # 綠色 (Hue: ~35-85)
    green_btn.click(
        fn=lambda: [None, 35, 85, 100, 255, 100, 255],
        inputs=[],
        outputs=[input_image, h_low, h_high, s_low, s_high, v_low, v_high]
    ).then(
        fn=process_and_update,
        inputs=inputs,
        outputs=outputs
    )
    
    # 藍色 (Hue: ~90-130)
    blue_btn.click(
        fn=lambda: [None, 90, 130, 100, 255, 100, 255],
        inputs=[],
        outputs=[input_image, h_low, h_high, s_low, s_high, v_low, v_high]
    ).then(
        fn=process_and_update,
        inputs=inputs,
        outputs=outputs
    )
    
    # 黃色 (Hue: ~20-35)
    yellow_btn.click(
        fn=lambda: [None, 20, 35, 100, 255, 100, 255],
        inputs=[],
        outputs=[input_image, h_low, h_high, s_low, s_high, v_low, v_high]
    ).then(
        fn=process_and_update,
        inputs=inputs,
        outputs=outputs
    )
    
    # 初始加載時自動生成測試圖像
    demo.load(
        fn=lambda: [create_test_image()],
        inputs=None,
        outputs=[input_image]
    ).then(
        fn=process_and_update,
        inputs=inputs,
        outputs=outputs
    )

# 啟動 Gradio 應用
if __name__ == "__main__":
    demo.launch()