File size: 13,771 Bytes
b328990
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
import numpy as np
import gradio as gr
import requests
import base64
import pandas as pd
import cv2
from typing import Tuple
from PIL import Image
from io import BytesIO

import os

from Model.Model6.model6_inference import main as model6_inferencer
from mmyolo.utils import register_all_modules

register_all_modules()


def get_access_token(refatch=False) -> str:
    """获取百度AI的access_token
    :param refatch:是否重新获取access_token
    :return:返回access_token"""
    if refatch:
        # client_id 为官网获取的AK, client_secret 为官网获取的SK
        client_id = '7OtH60uo01ZNYN4yPyahlRSx'
        client_secret = 'D5AxcUpyQyIA7KgPplp7dnz5tM0UIljy'
        host = 'https://aip.baidubce.com/oauth/2.0/token?' \
               'grant_type=client_credentials&client_id=%s&client_secret=%s' % (client_id, client_secret)
        response = requests.get(host)
        # print(response)
        if response:
            return response.json()['access_token']
    else:
        r"""
        {"refresh_token":"25.24b9368ce91f9bd62c8dad38b3436800.315360000.2007815067.282335-30479502",
         "expires_in":2592000,
         "session_key":
            "9mzdWT\/YmQ7oEi9WCRWbXd0YCcrSYQY6kKZjObKunlcKcZt95j9\/q1aJqbVXihpQOXK84o5WLJ8e7d4cXOi0VUJJcz5YEQ==",
         "access_token":"24.becefee37aba38ea43c546fc154d3016.2592000.1695047067.282335-30479502",
         "scope":"public brain_all_scope brain_body_analysis brain_body_attr brain_body_number brain_driver_behavior 
                  brain_body_seg brain_gesture_detect brain_body_tracking brain_hand_analysis wise_adapt 
                  lebo_resource_base lightservice_public hetu_basic lightcms_map_poi kaidian_kaidian 
                  ApsMisTest_Test\u6743\u9650 vis-classify_flower lpq_\u5f00\u653e cop_helloScope 
                  ApsMis_fangdi_permission smartapp_snsapi_base smartapp_mapp_dev_manage iop_autocar oauth_tp_app 
                  smartapp_smart_game_openapi oauth_sessionkey smartapp_swanid_verify smartapp_opensource_openapi 
                  smartapp_opensource_recapi fake_face_detect_\u5f00\u653eScope 
                  vis-ocr_\u865a\u62df\u4eba\u7269\u52a9\u7406 idl-video_\u865a\u62df\u4eba\u7269\u52a9\u7406 
                  smartapp_component smartapp_search_plugin avatar_video_test b2b_tp_openapi b2b_tp_openapi_online 
                  smartapp_gov_aladin_to_xcx","session_secret":"5c8c3dbb80b04f58bb33aa8077758679"
        }
        """
        access_token = "24.becefee37aba38ea43c546fc154d3016.2592000.1695047067.282335-30479502"
        return access_token


def resize_image(img, max_length=2048, min_length=50) -> Tuple[np.ndarray, bool]:
    """Ensure that the longest side is shorter than 2048px and the shortest side is longer than 50px.
    :param img: 前端传入的图片
    :param max_length: 最长边像素
    :param min_length: 最短边像素
    :return: 返回处理后的图片和是否进行了resize的标志
    """
    flag = False
    max_side = max(img.shape[0], img.shape[1])
    min_side = min(img.shape[0], img.shape[1])
    if max_side > max_length:
        scale = max_length / max_side
        img = cv2.resize(img, (int(img.shape[1] * scale), int(img.shape[0] * scale)))
        flag = True
    if min_side < min_length:
        scale = min_length / min_side
        img = cv2.resize(img, (int(img.shape[1] * scale), int(img.shape[0] * scale)))
        flag = True
    return img, flag


def model1_det(x):
    """人体检测与属性识别
    :param x:前端传入的图片
    :return:返回检测结果
    """

    def _Baidu_det(img):
        """调用百度AI接口进行人体检测与属性识别
        :param img:前端传入的图片,格式为numpy.ndarray
        :return:返回检测结果
        """
        request_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_attr"
        # 保存图片到本地
        cv2.imwrite('test.jpg', img)
        # 二进制方式打开图片文件
        f = open('test.jpg', 'rb')
        hex_image = base64.b64encode(f.read())
        # 选择二进制图片和需要输出的属性(12个)
        params = {
            "image": hex_image,
            "type": "gender,age,upper_wear,lower_wear,upper_color,lower_color,"
                    "orientation,upper_cut,lower_cut,side_cut,occlusion,is_human"
        }
        access_token = get_access_token()
        request_url = request_url + "?access_token=" + access_token
        headers = {'content-type': 'application/x-www-form-urlencoded'}
        response = requests.post(request_url, data=params, headers=headers)
        if response:
            return response.json()

    def _get_attributes_list(r) -> dict:
        """获取人体属性列表
        :param r:百度AI接口返回的json数据
        :return:返回人体属性列表
        """
        all_humans_attributes_list = {}
        person_num = r['person_num']
        print('person_num:', person_num)
        for human_idx in range(person_num):
            attributes_dict = r['person_info'][human_idx]['attributes']
            attributes_list = []
            for key, value in attributes_dict.items():
                attribute = [key, value['name'], value['score']]
                attributes_list.append(attribute)
            new_value = ['attribute', 'attribute_value', 'accuracy']
            attributes_list.insert(0, new_value)
            df = pd.DataFrame(attributes_list[1:], columns=attributes_list[0])
            all_humans_attributes_list[human_idx] = df
        return all_humans_attributes_list

    def _show_img(img, bboxes):
        """显示图片
        :param img:前端传入的图片
        :param bboxes:检测框坐标
        :return:处理完成的图片 """
        line_width = int(max(img.shape[1], img.shape[0]) / 400)
        for bbox in bboxes:
            left, top, width, height = bbox['left'], bbox['top'], bbox['width'], bbox['height']
            right, bottom = left + width, top + height
            for i in range(left, right):
                img[top:top + line_width, i] = [255, 0, 0]
                img[bottom - line_width:bottom, i] = [255, 0, 0]
            for i in range(top, bottom):
                img[i, left:left + line_width] = [255, 0, 0]
                img[i, right - line_width:right] = [255, 0, 0]
        return img

    result = _Baidu_det(x)
    HAs_list = _get_attributes_list(result)
    locations = []
    for i in range(len(result['person_info'])):
        locations.append(result['person_info'][i]['location'])

    return _show_img(x, locations), f"模型检测到的人数为:{result['person_num']}人"


def model2_rem(x):
    """背景消除
    :param x: 前端传入的图片
    :return: 返回处理后的图片
    """

    def _Baidu_rem(img):
        """调用百度AI接口进行背景消除
        :param img: 前端传入的图片,格式为numpy.ndarray
        :return: 返回处理后的图片
        """
        request_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_seg"
        bgr_image = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
        cv2.imwrite('test.jpg', bgr_image)
        f = open('test.jpg', 'rb')
        hex_image = base64.b64encode(f.read())
        params = {"image": hex_image}
        access_token = get_access_token()
        request_url = request_url + "?access_token=" + access_token
        headers = {'content-type': 'application/x-www-form-urlencoded'}
        response = requests.post(request_url, data=params, headers=headers)
        if response:
            encoded_image = response.json()["foreground"]
            decoded_image = base64.b64decode(encoded_image)
            image = Image.open(BytesIO(decoded_image))
            image_array = np.array(image)
            return image_array

    resized_x, resized_f = resize_image(x)
    new_img = _Baidu_rem(resized_x)
    if resized_f:
        resized_f = "图片尺寸已被修改至合适大小"
    else:
        resized_f = "图片尺寸无需修改"

    return new_img, resized_f


def model3_ext(x: np.ndarray, num_clusters=12):
    """主色调提取
    :param x: 前端传入的图片
    :param num_clusters: 聚类的数量
    :return: 返回主色调条形卡片"""

    # TODO: 编写颜色名称匹配算法[most important]
    # TODO: 修改颜色条形卡片呈现形式,要求呈现颜色名称和比例[important]
    def _find_name(color):
        """根据颜色值查找颜色名称
        :param color:颜色值
        :return:返回颜色名称
        """
        pass

    def _cluster(img, NUM_CLUSTERS):
        """K-means 聚类提取主色调
        :param img: 前端传入的图片
        :param NUM_CLUSTERS: 聚类的数量
        :return: 返回聚类结果
        """
        h, w, ch = img.shape
        reshaped_x = np.float32(img.reshape((-1, 4)))
        new_data_list = []
        for i in range(len(reshaped_x)):
            if reshaped_x[i][3] < 100:
                continue
            else:
                new_data_list.append(reshaped_x[i])
        reshaped_x = np.array(new_data_list)
        reshaped_x = np.delete(reshaped_x, 3, axis=1)
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
        NUM_CLUSTERS = NUM_CLUSTERS
        ret, label, center = cv2.kmeans(reshaped_x, NUM_CLUSTERS, None, criteria,
                                        NUM_CLUSTERS, cv2.KMEANS_RANDOM_CENTERS)
        clusters = np.zeros([NUM_CLUSTERS], dtype=np.int32)
        for i in range(len(label)):
            clusters[label[i][0]] += 1
        clusters = np.float32(clusters) / float(len(reshaped_x))
        center = np.int32(center)
        x_offset = 0
        card = np.zeros((50, w, 3), dtype=np.uint8)
        for c in np.argsort(clusters)[::-1]:
            dx = int(clusters[c] * w)
            b = center[c][0]
            g = center[c][1]
            r = center[c][2]
            cv2.rectangle(card, (x_offset, 0), (x_offset + dx, 50),
                          (int(b), int(g), int(r)), -1)
            x_offset += dx

        return card, resized_f

    resized_x, resized_f = resize_image(x)
    card, resized_f = _cluster(resized_x, num_clusters)
    if resized_f:
        resized_f = "图片尺寸已被修改至合适大小"
    else:
        resized_f = "图片尺寸无需修改"

    return card, resized_f


def model4_clo(x_path: str):
    def _get_result(input_path: str, cls_results: dict) -> pd.DataFrame:
        """convert the results of model6_2 to a dataframe
        :param input_path: the (absolute) path of the image
        :param cls_results: the results of model6_2

        :return: a dataframe to display on the web
        """
        result_pd = []
        img_name = os.path.basename(input_path)
        pred_profile = cls_results[img_name][0]['pred_class']
        pred_score = round(cls_results[img_name][0]['pred_score'], 2)
        result_pd.append([img_name, pred_profile, pred_score])
        df = pd.DataFrame(result_pd, columns=None)
        return df

    output_path_root = 'upload_to_web_tmp'
    if not os.path.exists(output_path_root):
        os.mkdir(output_path_root)
    cls_result = model6_inferencer(x_path, output_path_root)

    if cls_result:
        # use np to read image·
        x_name = os.path.basename(x_path)
        pred_x = np.array(Image.open(os.path.join(output_path_root, 'visualizations', x_name)))

        return pred_x, _get_result(x_path, cls_result), "识别成功!"
    # TODO: 完善识别失败时的处理(model6_inference.py中)[important]
    return x_path, pd.DataFrame(), "未检测到服装"


with gr.Blocks() as demo:
    gr.Markdown("# Flip text or image files using this demo.")
    with gr.Tab("人体检测模型"):
        with gr.Row():
            model1_input = gr.Image(height=400)
            model1_output_img = gr.Image(height=400)
            # model1_output_df = gr.DataFrame()
        model1_button = gr.Button("开始检测")
    with gr.Tab("背景消除模型"):
        with gr.Row():
            model2_input = gr.Image(height=400)
            model2_output_img = gr.Image(height=400)
        model2_button = gr.Button("开始消除")
    with gr.Tab('主色调提取'):
        with gr.Row():
            with gr.Column():
                # TODO: 参照“蒙娜丽莎”尝试修改前端界面[not important]
                # TODO: 修改布局,使其更美观[moderately important]
                model3_input = gr.Image(height=400, image_mode='RGBA')
                model3_slider = gr.Slider(minimum=1, maximum=20, step=1, value=12,
                                          min_width=400, label="聚类数量")
            model3_output_img = gr.Image(height=400)
        model3_button = gr.Button("开始提取")
    with gr.Tab("廓形识别"):
        with gr.Row():
            model4_input = gr.Image(height=400, type="filepath")
            model4_output_img = gr.Image(height=400)
            model4_output_df = gr.DataFrame(headers=['img_name', 'pred_profile', 'pred_score'],
                                            datatype=['str', 'str', 'number'])
        model4_button = gr.Button("开始识别")
    # 设置折叠内容
    with gr.Accordion("模型运行信息"):
        running_info = gr.Markdown("等待输入和运行...")

    model1_button.click(model1_det, inputs=model1_input, outputs=[model1_output_img, running_info])
    model2_button.click(model2_rem, inputs=model2_input, outputs=[model2_output_img, running_info])
    model3_button.click(model3_ext, inputs=[model3_input, model3_slider], outputs=[model3_output_img, running_info])
    model4_button.click(model4_clo, inputs=model4_input, outputs=[model4_output_img, model4_output_df, running_info])
demo.launch(share=True)