---
title: "How do I embed images for search in Python?"
description: "Embed images for search in Python: declare a CLIP index on the image column, rank by similarity, and keep vectors on the source row after insert."
url: "https://www.pixeltable.com/learn/how-to/embed-images-for-search"
updated: "2026-10-14"
doc: "https://docs.pixeltable.com/howto/cookbooks/search/search-similar-images"
---

# How do I embed images for search in Python?

Image embeddings map pictures into a vector space so similar stills can be ranked. CLIP embeddings put text and images in one space, which is how a sentence retrieves a photo. Indexing images for RAG means those vectors live on the rows that hold the files, so a new picture is searchable when it is inserted.

Updated: 2026-10-14
Part of [How do I ... in Python?](https://www.pixeltable.com/learn/how-to).

## Before you start

About 15 min.

- Python 3.11+
- pip install -U 'pixeltable[serve]'
- pxt init in the project root
- torch and transformers for CLIP

## On this page

- [Before you start](https://www.pixeltable.com/learn/how-to/embed-images-for-search#before-you-start)
- [Store pictures as an image column](https://www.pixeltable.com/learn/how-to/embed-images-for-search#step-1)
- [Declare CLIP embeddings on that column](https://www.pixeltable.com/learn/how-to/embed-images-for-search#step-2)
- [Search with a sentence or with another still](https://www.pixeltable.com/learn/how-to/embed-images-for-search#step-3)
- [Comparison](https://www.pixeltable.com/learn/how-to/embed-images-for-search#comparison)
- [Where Pixeltable fits](https://www.pixeltable.com/learn/how-to/embed-images-for-search#where-pixeltable-fits)
- [Questions](https://www.pixeltable.com/learn/how-to/embed-images-for-search#questions)

## 1. Store pictures as an image column {#step-1}

An Image column is the row you will index. A URL in a string is not an embedding. Captions are optional extra text on the same row.

```python
import pixeltable as pxt
from pixeltable.functions.huggingface import clip

TableModel = pxt.model_base()
clip_embed = clip.using(model_id='openai/clip-vit-base-patch32')

class Images(TableModel, name='images'):
    image: pxt.Image
    caption: pxt.String | None
```

## 2. Declare CLIP embeddings on that column {#step-2}

embedding= registers both CLIP overloads, so a sentence and a still share one index. That is how you index images for RAG: the vector is a property of the file row, not a copy in another store.

```python
class Images(TableModel, name='images'):
    image: pxt.Image
    caption: pxt.String | None
    __indexes__ = [
        pxt.EmbeddingIndex(image, embedding=clip_embed),
    ]
```

## 3. Search with a sentence or with another still {#step-3}

similarity(string=) ranks pictures against a phrase. similarity(image=) ranks against a picture. Both work because CLIP embeddings share one space.

```python
@pxt.query
def search_images(query: str, limit: int = 5):
    sim = Images.image.similarity(string=query)
    return (
        Images.order_by(sim, asc=False)
        .limit(limit)
        .select(Images.image, Images.caption, sim)
    )

# Image query: Images.image.similarity(image=still)
```

## Where image embeddings live {#comparison}

|  | Index on the image row | A separate vector database |
| --- | --- | --- |
| Vector | A column index on the file | A copy you upsert |
| Text query | CLIP similarity(string=) | Only if you also stored a text embedding |
| New file | Indexed on insert | A job that copies the vector |
| RAG | Retrieve the still, then generate | Retrieve an id, then join back to bytes |

## Where Pixeltable fits {#where-pixeltable-fits}

Pixeltable declares CLIP as EmbeddingIndex on the Image column. Image embeddings stay on the row that holds the file. Query with similarity(string=) or similarity(image=). A separate vector database is optional; see Pixeltable vs Pinecone when hosted ANN is the product.

```python
import pixeltable as pxt
from pixeltable.functions.huggingface import clip

TableModel = pxt.model_base()
clip_embed = clip.using(model_id='openai/clip-vit-base-patch32')

class Images(TableModel, name='images'):
    image: pxt.Image
    __indexes__ = [
        pxt.EmbeddingIndex(image, embedding=clip_embed),
    ]

@pxt.query
def search_images(query: str, limit: int = 5):
    sim = Images.image.similarity(string=query)
    return Images.order_by(sim, asc=False).limit(limit).select(Images.image, sim)
```

## Concepts

- [What is CLIP?](https://www.pixeltable.com/learn/what-is-clip)
- [What is an embedding index?](https://www.pixeltable.com/learn/what-is-an-embedding-index)
- [What is visual search?](https://www.pixeltable.com/learn/what-is-visual-search)

## Use case

- [Computer Vision Pipeline: Object Detection, Classification, and Search](https://www.pixeltable.com/use-cases/computer-vision-pipeline-optimization)

## Questions {#questions}

### Why CLIP embeddings instead of a text-only model? {#faq-1}

A text-only sentence transformer cannot embed a picture. CLIP maps images and text into one space, so a sentence retrieves a photo. That is the usual way to index images for RAG.

### Can I search with an image as well as a sentence? {#faq-2}

Yes. Images.image.similarity(string=query) ranks stills against a phrase. Images.image.similarity(image=still) ranks against a picture. Both read the same CLIP index.

### Do I copy vectors into Pinecone? {#faq-3}

Only if a hosted ANN service is already the serving contract. For typical image RAG, the index lives on the image column. Pixeltable vs Pinecone states that split.

## Related

- [What is CLIP?](https://www.pixeltable.com/learn/what-is-clip)
- [What is an embedding index?](https://www.pixeltable.com/learn/what-is-an-embedding-index)
- [What is visual search?](https://www.pixeltable.com/learn/what-is-visual-search)
- [Computer vision pipeline](https://www.pixeltable.com/use-cases/computer-vision-pipeline-optimization)
- [How do I build a multimodal RAG pipeline in Python?](https://www.pixeltable.com/learn/how-to/build-a-multimodal-rag-pipeline)
- [Pixeltable vs Pinecone](https://www.pixeltable.com/compare/pixeltable-vs-pinecone)
- [Pixeltable vs Voxel51](https://www.pixeltable.com/compare/pixeltable-vs-voxel51)
- [Find similar images with CLIP](https://docs.pixeltable.com/howto/cookbooks/search/search-similar-images)
