《------往期经典推荐------》
二、机器学习实战专栏【链接】,已更新31期,欢迎关注,持续更新中~~
三、深度学习【Pytorch】专栏【链接】
四、【Stable Diffusion绘画系列】专栏【链接】
五、YOLOv8改进专栏【链接】,持续更新中~~
六、YOLO性能对比专栏【链接】,持续更新中~
《------正文------》
引言
这篇文章重点介绍的是具有无数实际应用的功能:在智能手机、物联网设备和嵌入式系统等边缘设备上运行小型视觉语言模型(VLM)。这些模型在识别和指出物体方面变得越来越好。具体来说,它们擅长检测制造缺陷、计算可用停车位或发现癌细胞。本文将使用视觉语言模型对图中的钢管数量进行计数,效果如下。
使用模型:Molmo 7B
Molmo是由艾伦人工智能研究所创建的一组开放视觉语言模型。它们在PixMo上训练,PixMo是一个拥有100万个图像-文本对的数据集。基于Qwen 2 - 7 B和OpenAI CLIP构建的Molmo 7 B-D几乎与GPT-4V和GPT-4 o一样好用。
引擎:MLX-VLM
MLX-VLM是Prince Canuma(Blaizzy)开发的一款工具,用于在Mac上使用MLX运行和微调视觉语言模型(VLM)。它支持许多模型,如molmo,llava,llava_bunny,llava_next,mllama,multi_modality,paligemma,phi3_v,pixtral和qwen2_vl。这些模型可在MLX社区的Hugging Face上找到,您可以在那里免费下载。
MLX社区
Hugging Face上的MLX社区是一个分享Apple MLX框架的预转换模型权重的中心。它提供的模型可以用于训练、微调和部署大型语言模型(LLMs)和视觉模型等任务。已经实现的一些流行任务,如语音识别的耳语和图像生成的稳定扩散。用户还可以通过上传模型或在项目中使用MLX工具来做出贡献。
具体实现示例
我们将使用下面的图片来测试我们的工作流程。您可以替换图像并调整不同应用程序的提示。例如,您可以计算停车场中的汽车数量、人群中的人数或确定体育场中的空座位。本文将使用视觉语言模型对下图中的钢管数量进行检测计数。
首先,我们需要设置一个虚拟环境并安装所需的库。以下是步骤列表:
- 创建并激活虚拟环境。
- 安装必要的软件包:
pip install -U mlx-vlm
pip install einops
pip install torch torchvision
pip install matplotlib
在MLX中运行Molmo
在MLX中运行此模型非常容易。您可以复制并粘贴以下代码,然后就可以尝试这个模型了。请确保根据您的用例更改图像路径。对我来说,我将保留pipes_test.jpg
,在提示符中,我只会简单地问:“Point the pipes in the images。"【指向图像中的管道】
from mlx_vlm import load, apply_chat_template, generate
from mlx_vlm.utils import load_image
import matplotlib.pyplot as plt
model, processor = load("mlx-community/Molmo-7B-D-0924-4bit",processor_config={"trust_remote_code": True})
config = model.config
image_path = "pipes_test.jpg"
image = load_image(image_path)
messages = [{"role": "user", "content": "Point the pipes in the images"}]
prompt = apply_chat_template(processor, config, messages)
output = generate(model, processor, image, prompt, max_tokens=1200, temperature=0.7)
print(output)
上面的代码片段的输出如下:
<points x1="12.3" y1="76.8" x2="17.0" y2="63.9" x3="19.8" y3="49.0" x4="20.7" y4="80.6" x5="24.9" y5="66.7" x6="26.8" y6="50.8" x7="30.9" y7="84.8" x8="33.6" y8="70.2" x9="40.0" y9="88.3" alt="pipes in the images">pipes in the images</points>
然而,为了验证这个输出,我们需要对这些点进行后处理并绘制在我们的图像之上。
绘制输出结果
让我们实现两个函数:第一个用于解析点坐标,第二个用于绘制它们。在解析点时,需要注意的是,坐标是根据图像的宽度和高度进行规范化的。如下面的代码片段所示,我们需要将归一化值除以100,然后分别乘以图像的宽度和高度。
def parse_points(points_str):
# Function was taken from https://github.com/Blaizzy/mlx-vlm
if isinstance(points_str, tuple):
return points_str
x_coords = []
y_coords = []
# Handle multi-point format
if 'x1="' in points_str:
i = 1
while True:
try:
x = float(points_str.split(f'x{i}="')[1].split('"')[0])
y = float(points_str.split(f'y{i}="')[1].split('"')[0])
x_coords.append(x)
y_coords.append(y)
i += 1
except IndexError:
break
elif 'x="' in points_str:
x = float(points_str.split('x="')[1].split('"')[0])
y = float(points_str.split('y="')[1].split('"')[0])
x_coords.append(x)
y_coords.append(y)
try:
labels = points_str.split('alt="')[1].split('">')[0].split(", ")
item_labels = labels
except IndexError:
item_labels = [f"Point {i+1}" for i in range(len(x_coords))]
return x_coords, y_coords, item_labels
现在让我们使用Matplotlib来绘制图像顶部的点的位置。您也可以绘制标签。
def plot_locations(points: str | tuple, image, point_size=10, font_size=12):
if isinstance(points, str):
x_coords, y_coords, item_labels = parse_points(points)
else:
x_coords, y_coords, item_labels = points
grayscale_image = image.convert("L")
img_width, img_height = grayscale_image.size
x_norm = [(x / 100) * img_width for x in x_coords]
y_norm = [(y / 100) * img_height for y in y_coords]
if len(item_labels) != len(x_norm):
item_labels *= len(x_norm)
plt.figure(figsize=(10, 8))
plt.imshow(grayscale_image, cmap="gray")
plt.axis("off")
for i, (x, y, label) in enumerate(zip(x_norm, y_norm, item_labels), start=1):
label_with_number = f"{i}"
plt.plot(x, y, "o", color="red", markersize=point_size, label=label_with_number)
plt.annotate(
label_with_number,
(x, y),
xytext=(0, 10),
textcoords="offset points",
ha="center",
color="red",
fontsize=font_size,
)
plt.show()
最终结果
您可以看到管道被正确地标识,并且每个管道都有一个关联的ID。您可以修改代码并尝试许多其他用例。
好了,这篇文章就介绍到这里,喜欢的小伙伴感谢给点个赞和关注,更多精彩内容持续更新~~
关于本篇文章大家有任何建议或意见,欢迎在评论区留言交流!