# استخراج ميزات الصور

استخراج ميزات الصورة هو مهمة استخراج ميزات ذات دلالة دلالية من صورة معطاة. ولها العديد من حالات الاستخدام، بما في ذلك تشابه الصور واسترجاع الصور. علاوة على ذلك، يمكن استخدام معظم نماذج الرؤية الحاسوبية لاستخراج ميزات الصورة، حيث يمكن إزالة الرأس الخاص بالمهمة (تصنيف الصور، كشف الأشياء، إلخ) والحصول على الميزات. هذه الميزات مفيدة جداً على مستوى أعلى: كشف الحواف، وكشف الزوايا، وما إلى ذلك. وقد تحتوي أيضاً على معلومات عن العالم الحقيقي (مثل شكل القطة) اعتماداً على عمق النموذج. وبالتالي، يمكن استخدام هذه المخرجات لتدريب مصنفات جديدة على مجموعة بيانات محددة.

في هذا الدليل، ستقوم بما يلي:

- تعلّم كيفية بناء نظام بسيط لتقارب الصور فوق خط أنابيب `image-feature-extraction`.
- أنجز المهمة نفسها باستخدام الاستدلال على النموذج الخام.

## التشابه بين الصور باستخدام خط أنابيب `image-feature-extraction`

لدينا صورتان لقطتين جالستين على شبكة صيد سمك، إحداهما مُولّدة.

```python
from PIL import Image
import requests

img_urls = ["https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/cats.png", "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/cats.jpeg"]
image_real = Image.open(requests.get(img_urls[0], stream=True).raw).convert("RGB")
image_gen = Image.open(requests.get(img_urls[1], stream=True).raw).convert("RGB")
```

لننظر إلى خط المعالجة أثناء العمل. أولاً، قم بتبويب خط المعالجة. إذا لم تقم بتمرير أي نموذج إليه، فسيتم تهيئة خط المعالجة تلقائياً باستخدام [google/vit-base-patch16-224](https://huggingface.co/google/vit-base-patch16-224). إذا كنت ترغب في حساب التشابه، فاضبط `pool` على True.

```python
import torch
from transformers import pipeline
from accelerate import Accelerator
# automatically detects the underlying device type (CUDA, CPU, XPU, MPS, etc.)
device = Accelerator().device
pipe = pipeline(task="image-feature-extraction", model="google/vit-base-patch16-384", device=device, pool=True)
```

لإجراء الاستدلال باستخدام `pipe`، مرّر كلا الصورتين إليه.

```python
outputs = pipe([image_real, image_gen])
```

تحتوي المخرجات على تمثيلات مجمّعة لهاتين الصورتين.

```python
# get the length of a single output
print(len(outputs[0][0]))
# show outputs
print(outputs)

# 768
# [[[-0.03909236937761307, 0.43381670117378235, -0.06913255900144577,
```

للحصول على درجة التشابه، نحتاج إلى تمريرها إلى دالة تشابه.

```python
from torch.nn.functional import cosine_similarity

similarity_score = cosine_similarity(torch.Tensor(outputs[0]),
                                     torch.Tensor(outputs[1]), dim=1)

print(similarity_score)

# tensor([0.6043])
```

إذا كنت ترغب في الحصول على حالات الإخفاء الأخيرة قبل التجميع، فتجنب تمرير أي قيمة لباراميتر `pool`، إذ تكون قيمته الافتراضية `False`. تُعدّ هذه حالات الإخفاء مفيدة لتدريب مصنّفات أو نماذج جديدة مبنية على الميزات المستخرجة من النموذج.

```python
pipe = pipeline(task="image-feature-extraction", model="google/vit-base-patch16-224", device=device)
outputs = pipe(image_real)
```

بما أن المخرجات غير مجمّعة، نحصل على حالات الإخفاء الأخيرة حيث يكون البُعد الأول هو حجم الدفعة، والبعدين الأخيرين هما شكل التضمين.

```python
import numpy as np
print(np.array(outputs).shape)
# (1, 197, 768)
```

## الحصول على الميزات والتشابهات باستخدام `AutoModel`

يمكننا أيضًا استخدام فئة `AutoModel` من مكتبة transformers للحصول على الميزات. يقوم `AutoModel` بتحميل أي نموذج من نماذج transformers دون رأس مخصص لمهمة معينة، ويمكننا استخدام ذلك للحصول على الميزات.

```python
from transformers import AutoImageProcessor, AutoModel

processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
model = AutoModel.from_pretrained("google/vit-base-patch16-224").to(device)
```

لنكتب دالة بسيطة للاستدلال. سنمرر المدخلات إلى `processor` أولاً ثم نمرر مخرجاتها إلى `model`.

```python
def infer(image):
  inputs = processor(image, return_tensors="pt").to(device)
  outputs = model(**inputs)
  return outputs.pooler_output
```

يمكننا تمرير الصور مباشرةً إلى هذه الدالة والحصول على التضمينات.

```python
embed_real = infer(image_real)
embed_gen = infer(image_gen)
```

يمكننا الحصول على التشابه مرة أخرى عبر التضمينات.

```python
from torch.nn.functional import cosine_similarity

similarity_score = cosine_similarity(embed_real, embed_gen, dim=1)
print(similarity_score)

# tensor([0.6061], device='cuda:0', grad_fn=<SumBackward1>)
```

