Picture using minio service

This commit is contained in:
zhouchengrong
2024-03-18 14:17:43 +08:00
parent 26c328b1e4
commit 2f89e7432f
116 changed files with 10294 additions and 254 deletions

View File

@@ -1,3 +1,5 @@
import io
import requests
from PIL import Image
@@ -6,14 +8,22 @@ import numpy as np
import tritonclient.http as httpclient
import torch
from matplotlib import pyplot as plt, image as mpimg
from minio import Minio
from torchvision import transforms
from foco import extract_main_colors
from app.core.config import MINIO_IP, MINIO_ACCESS, MINIO_SECRET, MINIO_SECURE, MINIO_PORT, OM_TRITON_PORT, OM_TRITON_IP
from app.service.outfit_matcher.foco import extract_main_colors
from app.service.utils.decorator import RunTime
class OutfitMatcher(object):
def __init__(self):
self.tritonclient = httpclient.InferenceServerClient(url="10.1.1.240:10010")
self.minio_client = Minio(
f"{MINIO_IP}:{MINIO_PORT}",
access_key=MINIO_ACCESS,
secret_key=MINIO_SECRET,
secure=MINIO_SECURE)
@staticmethod
def pad_array(input_value, value=0):
@@ -66,64 +76,83 @@ class OutfitMatcher(object):
cv2.subtract(img, mean, img) # inplace
cv2.multiply(img, stdinv, img) # inplace
return img
@RunTime
def visualize(self, outfits, scores, topk=5, best=True, output_path=None):
# 将outfits和scores按照scores的值进行排序
sorted_indices = np.argsort(-scores.flatten() if best else scores.flatten())[:topk] # 使用负号进行降序排序
outfits = [outfits[i] for i in sorted_indices]
scores = scores[sorted_indices]
# 设置子图的行列数
num_rows = len(outfits)
num_cols = max([len(x) for x in outfits]) + 1 # 一个是图片,一个是分数
# 创建一个新的图像,并指定子图的行列数
fig, axes = plt.subplots(num_rows, num_cols, figsize=(8, 15))
title = f"Best {topk} Outfits" if best else f"Worst {topk} Outfits"
fig.suptitle(title, fontsize=16)
# 遍历每套outfit并将其显示在对应的子图中
for i, (outfit, score) in enumerate(zip(outfits, scores)):
# 显示分数
axes[i, 0].text(0.1, 0.5, f"Score: {score[0]:.4f}", fontsize=12)
axes[i, 0].axis("off")
# 显示图片
for j, item in enumerate(outfit):
img = mpimg.imread(item['image_path']) # 读取图片
axes[i, j + 1].imshow(img) # 在对应的子图中显示图片
axes[i, j + 1].axis('off') # 关闭坐标轴
axes[i, j + 1].set_title(item["semantic_category"], fontsize=10)
for j in range(len(outfit), num_cols):
axes[i, j].axis("off")
# 在每一行的底部添加一条横线
axes[i, 0].axhline(y=0, color='black', linewidth=1)
# 隐藏最后一行的横线
axes[-1, 0].axhline(y=0, color='white', linewidth=1)
# 调整布局
plt.subplots_adjust(wspace=0.1, hspace=0.1)
plt.tight_layout()
outfits = [outfits[i] for i in sorted_indices] # 最好或最差的五个
scores = scores[sorted_indices] # 这五个的分数
# 是否画出来
if output_path:
plt.savefig(output_path)
# 设置子图的行列数
num_rows = len(outfits)
num_cols = max([len(x) for x in outfits]) + 1 # 一个是图片,一个是分数
# 创建一个新的图像,并指定子图的行列数
fig, axes = plt.subplots(num_rows, num_cols, figsize=(8, 15))
title = f"Best {topk} Outfits" if best else f"Worst {topk} Outfits"
fig.suptitle(title, fontsize=16)
# 遍历每套outfit并将其显示在对应的子图中
for i, (outfit, score) in enumerate(zip(outfits, scores)):
# 显示分数
axes[i, 0].text(0.1, 0.5, f"Score: {score[0]:.4f}", fontsize=12)
axes[i, 0].axis("off")
# 显示图片
for j, item in enumerate(outfit):
img = mpimg.imread(item['image_path']) # 读取图片
axes[i, j + 1].imshow(img) # 在对应的子图中显示图片
axes[i, j + 1].axis('off') # 关闭坐标轴
axes[i, j + 1].set_title(item["semantic_category"], fontsize=10)
for j in range(len(outfit), num_cols):
axes[i, j].axis("off")
# 在每一行的底部添加一条横线
axes[i, 0].axhline(y=0, color='black', linewidth=1)
# 隐藏最后一行的横线
axes[-1, 0].axhline(y=0, color='white', linewidth=1)
# 调整布局
plt.subplots_adjust(wspace=0.1, hspace=0.1)
plt.tight_layout()
if output_path:
plt.savefig(output_path)
else:
plt.show()
else:
plt.show()
return outfits, scores.numpy().flatten().tolist()
class OutfitMatcherHon(OutfitMatcher):
def __init__(self):
super().__init__()
@staticmethod
def load_image(img_path):
if 'http' in img_path:
file = requests.get(img_path)
image = cv2.imdecode(np.fromstring(file.content, np.uint8), 1)
image = Image.fromarray(image.astype('uint8'), 'RGB')
else:
image = Image.open(img_path).convert('RGB')
return np.array(image)
def load_image(self, img_path):
try:
# 从 MinIO 中获取对象(图像文件)
image_data = self.minio_client.get_object(img_path.split("/", 1)[0], img_path.split("/", 1)[1])
# 读取图像数据并转换为 PIL 图像对象
pil_image = Image.open(io.BytesIO(image_data.read()))
# 将 PIL 图像转换为 NumPy 数组
image_array = np.array(pil_image)
return image_array
except Exception as e:
print(f"An error occurred: {e}")
return None
# if 'http' in img_path:
# file = requests.get(img_path)
# image = cv2.imdecode(np.fromstring(file.content, np.uint8), 1)
# image = Image.fromarray(image.astype('uint8'), 'RGB')
# else:
# image = Image.open(img_path).convert('RGB')
# return np.array(image)
@staticmethod
def resize_image(img):
@@ -190,18 +219,34 @@ class OutfitMaterTypeAware(OutfitMatcher):
'outerwear', 'scarves', 'shoes', 'sunglasses', 'tops'
]
@RunTime
def __init__(self):
super().__init__()
@staticmethod
def load_image(img_path):
if 'http' in img_path:
file = requests.get(img_path)
image = cv2.imdecode(np.fromstring(file.content, np.uint8), 1)
image = Image.fromarray(image.astype('uint8'), 'RGB')
else:
image = Image.open(img_path).convert('RGB')
return image
@RunTime
# TODO 用多线程读图片
def load_image(self, img_path):
try:
# 从 MinIO 中获取对象(图像文件)
image_data = self.minio_client.get_object(img_path.split("/", 1)[0], img_path.split("/", 1)[1])
# 读取图像数据并转换为 PIL 图像对象
pil_image = Image.open(io.BytesIO(image_data.data)).convert("RGB")
# 将 PIL 图像转换为 NumPy 数组
# image_array = np.array(pil_image)
return pil_image
except Exception as e:
print(f"An error occurred: {e}")
return None
# if 'http' in img_path:
# file = requests.get(img_path)
# image = cv2.imdecode(np.fromstring(file.content, np.uint8), 1)
# image = Image.fromarray(image.astype('uint8'), 'RGB')
# else:
# image = Image.open(img_path).convert('RGB')
# return np.array(image)
@staticmethod
def resize_image(img):
@@ -229,7 +274,6 @@ class OutfitMaterTypeAware(OutfitMatcher):
image = self.load_image(item["image_path"])
image = self.resize_image(image)
images.append(image)
category = self.base_fashion_categories.index(item["mapped_cate"])
categories.append(category)
images = np.stack(images, axis=0)
@@ -240,6 +284,7 @@ class OutfitMaterTypeAware(OutfitMatcher):
outfit_categories, _ = self.pad_array(outfit_categories, value=len(self.base_fashion_categories))
return outfit_images, outfit_categories, mask
@RunTime
def get_result(self, outfits):
"""Input outfits structure and output scores.
Args:
@@ -272,7 +317,7 @@ class OutfitMaterTypeAware(OutfitMatcher):
scores: List of float
"""
image, category, mask = self.preprocess(outfits)
client = httpclient.InferenceServerClient(url="localhost:8000")
client = httpclient.InferenceServerClient(url=f"{OM_TRITON_IP}:{OM_TRITON_PORT}")
# 输入集
inputs = [
httpclient.InferInput("input__0", image.shape, datatype="FP32"),
@@ -290,4 +335,4 @@ class OutfitMaterTypeAware(OutfitMatcher):
# 推理
# 取结果
scores = torch.from_numpy(results.as_numpy("output__0"))
return scores # Shape (N, 1)
return scores # Shape (N, 1)