# Pet Photographer: Create a Data Filtering Module

If your machine [captures](https://docs.viam.com/data/capture-sync/capture-and-sync-data/) a lot of data, you might want to filter captured data to selectively store only the data you are interested in.
For example, you might want to use your smart machine’s camera to capture images based on specific criteria, such as the presence of a certain color, and omit captured images that don’t meet that criteria.

In this tutorial, you will use a custom module to function as a color filter, and use it with a [camera](https://docs.viam.com/reference/components/camera/) to only capture images where your pet is in the frame in the following way:

1. Attach a colored object, such as a blue collar, to your pet.
2. Set up a camera in an area where your pet is likely to appear in the frame, and configure the data management service to capture and sync images from that camera.
3. Configure the `colorfilter` custom module to filter captured images from your camera, saving them only when your pet, along with their easily-identifiable colored object, is present in the frame.

The source code for this module is available on the [`modular-filter-examples` GitHub repository](https://github.com/viam-labs/modular-filter-examples). In addition to the `colorfilter` module used in this tutorial, the example repository also includes a [sensor reading filter](https://github.com/viam-labs/modular-filter-examples/tree/main/sensorfilter) which you could use to control and filter the data recorded by a [sensor component](https://docs.viam.com/reference/components/sensor/).

## Hardware requirements

To create your own filtering pet photographer robot, you’ll need the following hardware:

- A computer  
- A [webcam](https://docs.viam.com/reference/components/camera/webcam/) or other type of [camera](https://docs.viam.com/reference/components/camera/)  
- A colored object, such as a blue collar for enhanced accuracy _(optional)_

#### Tip

In this tutorial, the camera is configured to identify and filter images with the color blue, as it is less common in many environments.
If your pet already has a distinct color that is different from their environment, you can also configure your camera to use that color to identify pictures of your pet.

Make sure your webcam is connected to your computer.

## Setup

Add a new machine on [Viam](https://app.viam.com/). On the machine’s page, follow the setup instructions to install `viam-server` on the computer you’re using for your project. Wait until your machine has successfully connected to Viam.

#### Note

Your `viam-server` must be [version 0.8.0](https://github.com/viamrobotics/rdk/releases/tag/v0.8.0-rc0) or newer, as filtering capabilities were introduced in the RDK starting from that version.

Then, install [Go](https://go.dev/dl/) or [Python](https://www.python.org/downloads/) on both your local development computer and on your machine’s board if they are not the same device.

## Add the custom module

In this tutorial, you can choose to add custom data filtering to your machine in one of two ways:

1. [Download the `colorfilter` module](https://docs.viam.com/tutorials/configure/pet-photographer/#download-the-colorfilter-module) from Viam and get started quickly.
2. [Code your own color filtering module](https://docs.viam.com/tutorials/configure/pet-photographer/#code-your-own-module), exploring the process of building a module from scratch.

### Download the colorfilter module

Follow the instructions below to download the `colorfilter` module in your preferred programming language:

- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-1-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-1-1)

1. Clone the [`colorfilter` module](https://github.com/viam-labs/modular-filter-examples) from GitHub onto your computer:
```
git clone https://github.com/viam-labs/modular-filter-examples.git
```

2. Navigate to the Python color filter directory, `pycolorfilter`.
3. Note the path to your module’s executable, run.sh, for later use.
4. [Add the `colorfilter` module to your smart machine as a local module](https://docs.viam.com/tutorials/configure/pet-photographer/#add-as-a-local-module) and continue the tutorial from there.

1. Clone the [`colorfilter` module](https://github.com/viam-labs/modular-filter-examples) from GitHub onto your machine’s computer:
```
git clone https://github.com/viam-labs/modular-filter-examples.git
```

2. Navigate to the Go color filter directory, `colorfilter`.
3. Inside of the `module` directory, [compile the executable](https://docs.viam.com/build-modules/write-a-driver-module/#3-test-locally) that runs your module.
4. Save the path to your module’s executable for later use.
5. [Add the `colorfilter` module to your smart machine as a local module](https://docs.viam.com/tutorials/configure/pet-photographer/#add-as-a-local-module) and continue the tutorial from there.

### Code your own module

To code your own color filtering module, first create the necessary files and directories on your smart machine:

- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-2-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-2-1)

1. Create a folder for your module with the name of your model `colorfilter`.
   - Your model name must use all lowercase letters.
2. Inside that folder, create a file called color_filter.py.

1. Create a folder for your module with the name of your model `colorfilter`.
   - Your model name must use all lowercase letters.
2. Inside that folder, create:
   - A file called color_filter.go.
   - A directory named `module`.

#### Code a filter resource model

Next, include all the methods that the corresponding Viam SDK requires in its API definition.

- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-3-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-3-1)

You can write your own code or copy the code from the `colorfilter` module’s [color_filter.py](https://github.com/viam-labs/modular-filter-examples/blob/main/pycolorfilter/color_filter.py) file.

To write your own code, implement a client interface defined by the required methods outlined in the client.py file for the specific resource you are implementing. For example, the camera’s client.py file is located at [/components/camera/client.py](https://github.com/viamrobotics/viam-python-sdk/blob/main/src/viam/components/camera/client.py).

1. Open the color_filter.py file you just created and implement the required methods from client.py.  
   - Exclude the `get_images` method, which you will customize to add filtering functionality in the upcoming section.  
   - Include the other methods within the class corresponding to your resource type (in this case, the `CameraClient` class).

For more information, refer to [Write your new resource model definition](https://docs.viam.com/build-modules/write-a-driver-module/#2-implement-the-resource-api).

To write your own code, implement a client interface defined by the required methods outlined in the client.go file for the specific resource you are implementing. For example, the camera’s client.go file is located at [/components/camera/client.go](https://github.com/viamrobotics/rdk/blob/main/components/camera/client.go).

1. Open the color_filter.go file you just created and implement the required methods in it.  
   Exclude the `Images` method, which you will customize to add filtering functionality in the upcoming section.  
   - You can create your own code or copy the code from the [viam-labs `colorfilter` repository’s color_filter.go](https://github.com/viam-labs/modular-filter-examples/blob/main/colorfilter/color_filter.go) file.

The filter function in your custom filter module must contain two critical elements:

1. A utility function that will check if the caller of the filter function is the [data management service](https://docs.viam.com/data/capture-sync/capture-and-sync-data/).
2. A safeguard that ensures if the data management service is not the caller, an error and the unfiltered data is returned.

#### Important

You must include both the safeguard and utility functions in order to access data filtering functionality within your module.

For programming languages other than Python and Go, the API of the component you’re receiving data from will provide comparable utility functions and safeguards. These tools help you to check the caller of your filter function and ensure your smart machine responds accordingly.

For detailed information, please refer to the documentation for your chosen SDK.

Follow the steps below to include the utility function and check whether the data management service is the caller of the function responsible for data capture.  
If a service other than the data management service calls the function, it will return the original, unfiltered data.

To check the caller of the collector function using the utility function:

- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-4-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-4-1)

First, import `from_dm_from_extra`:
```python

```

Then, include it in the conditional statement in your filter function:
```python

```
With this configuration:
- Your camera checks if the data management service is the caller of the filter function by using `from_dm_from_extra`.

Write a conditional statement that checks `FromDMContextKey`:
#### Important

Use `FromDMContextKey` to check the caller of the data capture function when working with a modular _camera_ using the Go SDK. For all other components, you should use `FromDMString` instead. See the [sensor filter example](https://github.com/viam-labs/modular-filter-examples/blob/main/sensorfilter/sensor_filter.go) for example code to support working with a sensor.
```go

```
With this configuration:
- Your camera gets images from the underlying camera, then checks if the data management service is the caller of the filter function by using `FromDMContextKey`.
- If `FromDMContextKey` is `true` and the data management service is the caller, the code requests detections on the captured image.

After implementing a check to identify the initiator of the filter function, you must include the safeguard that will return an error if the data management service is not the caller.
To do this, include the following in your filter module’s resource model:
- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#example-tabs-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#example-tabs-1)  
Edit color_filter.py and import the safeguard error `NoCaptureToStoreError` from Viam:
```python

```

Then, edit the `if from_dm_from_extra(extra)` conditional statement from earlier to add a second conditional statement within it that returns the error when the data management service is not the caller:
```python

```
This code:
- Checks the length (`len`) of the `detections` variable.
- Raises a `NoCaptureToStoreError()` if `len` is equal to `0` to signify that the data management service is not the caller.

Open color_filter.go and write a conditional statement inside of your filter function that includes the error message `data.ErrNoCaptureToStore`:
```go

```
This code:
- Checks the length (`len`) of the `detections` variable.
- Raises a `data.ErrNoCaptureToStore` error if `len` is equal to `0` to signify that the data management service is not the caller.

Now that you’ve included the required utility function and safeguard, your complete color filter function should look like the following:
- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-6-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-6-1)  
```python

```
If the data management service is the caller, the filter function requests detections from the vision service and returns the image if the specified color is detected.
Otherwise, it raises a `NoCaptureToStoreError()` error.

This code includes the utility function and safeguard you implemented earlier, and also includes error handling for getting images and obtaining detections.
```go

```
If the data management service is the caller, the filter function requests detections from the vision service and returns the image if the specified color is detected.
Otherwise, it raises a `data.ErrNoCaptureToStore` error.

After you have implemented your resource API’s required methods and written your filter function, your final code should look like this:
- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-7-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-7-1)  
color_filter.py implements “colorfilter”, a custom model of the [camera component API](https://docs.viam.com/reference/components/camera/).

Click to view sample code from color_filter.py
```python

```
In this code:
- The Python SDK simplifies the verification process by exposing the utility function `from_dm_from_extra`, to see if the caller is the data management service for you.
- If the boolean is `true`, the function will call the vision service to get detections and return the image if the color is detected. Otherwise, it raises `NoCaptureToStoreError()`.

color_filter.go implements “colorfilter”, a custom model of the [camera component API](https://docs.viam.com/reference/components/camera/).

Click to view sample code from color_filter.go
```go

```
In this code:
- The `Images` method gets images from the underlying camera, then checks if the data management service is the caller using `ctx.Value(data.FromDMContextKey{})`.
- If `true`, the function calls the vision service to get detections and returns the images if the color is detected. Otherwise, it raises the [`ErrNoCaptureToStore`](https://github.com/viamrobotics/rdk/blob/214879e147970a454f78035e938ea853fcd79f17/data/collector.go#L44) error.

For more information, see [Write your new resource model definition](https://docs.viam.com/build-modules/write-a-driver-module/#2-implement-the-resource-api).

#### Code an entry point file

Next, code your module entry point file which `viam-server` will use to initialize and start the filter module.

To code an entry point file yourself, locate the API as defined in the relevant `<resource-name>/<resource-name>.go` file in the [RDK source code](https://github.com/viamrobotics/rdk).
- In this example, the camera’s API is defined in the [camera.go](https://github.com/viamrobotics/rdk/blob/main/components/camera/camera.go) file in the RDK source code. When developing your main.go or main.py file, reference this file.
- [Python](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-8-0)  
- [Go](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-8-1)

Follow these steps to code your entry point file:
1. Inside of your filter module’s directory, create a new file named main.py.
   This will be the entry point file for the module.
2. Add the code below which initializes and starts the filter module.
```python

```

Follow these steps to code your entry point file:
1. Open the folder named `module` inside of your filter module’s directory and create a new file named main.go.
   This will be the entry point file for the module.
2. Add the code below which initializes and starts the filter module.
```go

```
For more information, see [Create a new module](https://docs.viam.com/build-modules/write-a-driver-module/).

Once you’ve written your filter module, [compile your module into a single executable](https://docs.viam.com/build-modules/write-a-driver-module/#3-test-locally) that runs your module when executed. Note the absolute path to your module’s executable for use in the next section.

### Add as a local module

Whether you’ve downloaded the `colorfilter` module, or written your own color filtering module, the next step is to add the module to your smart machine as a local module:

1. Navigate to the **CONFIGURE** tab of your machine’s page.  
2. Click the **+** (Create) button next to your main part in the left-hand menu and select **Local module**, then **Local module**.  
3. Enter a name or use the suggested name for your local module, enter the [module’s executable path](https://docs.viam.com/build-modules/write-a-driver-module/#3-test-locally), then click **Create**.  
   - The name must use only lowercase characters.
4. Then, click the **Save** button in the top right corner of the page to save your changes.

## Add services

Next, add the following services to your smart machine to support the color filter module:

- The [data management service](https://docs.viam.com/data/capture-sync/capture-and-sync-data/) enables your smart machine to capture data and sync it to the cloud.
- The [vision service](https://docs.viam.com/reference/apis/services/vision/#detections) enables your smart machine to perform color detection on objects in a camera stream.

### Add the data management service

To enable data capture on your machine, add and configure the [data management service](https://docs.viam.com/data/capture-sync/capture-and-sync-data/) to capture and store data on your machine’s computer:

- [Config Builder](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-9-0)  
- [JSON Template](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-9-1)

1. On the **CONFIGURE** tab, click the **+** icon next to your machine part in the left-hand menu and select **Blocks**.
2. Search for `data management`, then select the `data_manager/builtin` block.
3. Enter a name or use the suggested name for your instance of the data manager. This tutorial uses the name ‘dm’ in all example code.
4. Click **Add to machine**. On the panel that appears, you can manage the capturing and syncing functions individually. By default, the data management service captures data every 0.1 minutes to the ~/.viam/capture directory. Leave the default settings as they are.
5. Click **Save** in the top right corner of the screen to save your changes.

For more detailed information, see [Add the data management service](https://docs.viam.com/data/capture-sync/capture-and-sync-data/).

Add the data management service to the services array in your rover’s raw JSON configuration:
```json

```

### Add the vision service

To enable your smart machine to detect a specific color in its camera stream, add a [`color_detector` vision service](https://docs.viam.com/reference/services/vision/color_detector/). For this tutorial, we will configure the vision service to recognize a blue dog collar using `#43A1D0` or `rgb(67, 161, 208)`. If you have a different item you want to use, or want to match to a color that matches your pet closely, you can use a different color.

- [Config Builder](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-10-0)  
- [JSON Template](https://docs.viam.com/tutorials/configure/pet-photographer/#tabset-tutorialsconfigurepet-photographer-10-1)

1. Navigate to the **CONFIGURE** tab of your machine’s page.  
2. Click the **+** icon next to your machine part in the left-hand menu and select **Blocks**.  
3. Search for `color detector`, then select the `vision/color_detector` block.  
4. Enter a name or use the suggested name for your color detector. This tutorial uses the name ‘my_color_detector’ in all example code.  
5. click **Add to machine**.
6. In the vision service’s **Attributes** section, click the color selection box to set the color to detect. For this tutorial, set the color to `#43A1D0` or `rgb(67, 161, 208)`. Alternatively, you can provide the color of your pet, or use a different brightly-colored collar or ribbon.
7. Set **Hue Tolerance** to `0.06` and **Segment size px** to `100`.
8. Click the **Save** button in the top right corner of the page.

Your configuration should look like the following:

For more detailed information, refer to [Configure a color detector](https://docs.viam.com/reference/services/vision/color_detector/).

Add the vision service object to the services array in your rover’s raw JSON configuration:
```json

```

Click the **Save** button in the top right corner of the page when done.

## Enable filtering by color

With the vision and data management services configured, you can now configure your camera to filter by color and sync photos to Viam’s cloud.

### Configure your camera

If you haven’t already, add a [camera](https://docs.viam.com/reference/components/camera/) component to your smart machine:

1. On the **CONFIGURE** tab, click the **+** (Create) button next to your main part in the left-hand menu and select **Blocks**. Start typing “webcam” and select **camera / webcam**. Enter a name or use the suggested name for your camera. This tutorial uses the name ‘cam’ in all example code. Click **Add to machine**.

2. Leave the **video_path** blank and the camera will use the default video path for your machine. If this doesn’t work when you test your camera later, you can try a different video path by following the prompt in the camera’s configuration panel.
3. Click **Save** in the top right corner of the screen to save your changes.

### Add the color filter component

1. Click the **+** icon next to your machine part in the left-hand menu and select **Local module**, then **Local component**.
2. On the **Create** menu:
   1. Select the `camera` type from the dropdown menu.
   2. Select or enter `example:camera:colorfilter`, the model namespace triplet of your modular resource’s model.
   3. Provide a name for this instance of your modular resource. This name must be different from the module name.

3. Click **Create** to create the modular resource.
4. In the resulting module configuration pane, copy the following JSON configuration into the attributes field:
```json

```

### Configure data capture

To add data capture for the color filter camera:

1. Click **Add method** in the **Data capture** section of your color filter camera component.
2. Toggle the **Method** dropdown menu, select **GetImages**, and set the **Frequency** of the capture to `0.1`, which will configure the data management service to capture images from your camera once every 10 seconds.
3. Click the **MIME type** dropdown and select `image/jpeg`.
4. Click **Save** in the top right corner of the screen.

## Test your color filter camera

To test that your color filter camera is capturing and filtering images properly, navigate to the **CONTROL** tab on your machine’s page.

On the **colorfiltercam** panel, toggle **View colorfiltercam** to view your camera’s live feed. Test the filter by positioning your smart machine so that it captures an image of your pet wearing its collar. Then examine the **DATA** tab to confirm that only pictures containing your pet wearing their collar are stored.

For example, the following is the result of several dozen pictures of the same dog, but only those pictures where he is wearing the blue collar were captured and synced to the cloud:

## Next steps

Your pet photographer is now set up. Place it in an area your pet frequently visits and don’t forget to attach the colored object to your pet.

Now you can follow similar steps and customize the code you’ve written to configure a sensor for detecting specific thresholds or filter out blurry images from your camera’s captures.

Try these other tutorials for more on working with the data management and vision services:

\
\
Smart Pet Treat Dispenser\
\
Use a Raspberry Pi, a motor, and machine learning to build a smart pet feeder.](https://docs.viam.com/tutorials/projects/pet-treat-dispenser/)

[There should have been a video here but your browser does not seem to support it.\
\
Pet Guardian\
\
Make a functional guardian with a servo motor, some LEDs, a camera, and the ML Model and vision service to detect people and pets.](https://docs.viam.com/tutorials/projects/guardian/)

\
\
Detect a Person and Send a Photo\
\
Use the vision service and the Python SDK to send yourself a text message when your webcam detects a person.](https://docs.viam.com/tutorials/projects/send-security-photo/)

[Deploy a model from the registry\
\
Pick a pre-trained ML model from the Viam registry, deploy it to your machine, and wire it through an ML model service so a vision service can use it.](https://docs.viam.com/vision/deploy-and-maintain/deploy-from-registry/)
