🧱 How to Create Your Own Component

You can create a custom component from scratch locally and then upload it to the PipeLogic workspace. This gives you complete control over the structure, logic, and configuration.

πŸ› οΈ What We’re Building

A PipeLogic component that takes an input of type Image and returns a grayscale image using OpenCV. The input and output types are both Image.

Step-by-Step Instructions to Create your own Component

πŸ“ STEP 1: Create the component folder

Open your WSL terminal and run:

mkdir convert_image_grayscale
cd convert_image_grayscale

πŸ“ STEP 2: Create folders and files

Run these commands to create the needed subfolders and files:

mkdir src
touch component.yml
touch .pipecomponent
touch src/requirements.txt
touch src/main.py

πŸ“¦ STEP 3: Add Dependencies to requirements.txt

Open src/requirements.txt in your preferred text editor and add:

pipelogic
numpy
opencv-python-headless

πŸ“ STEP 4: Edit component.yml

Open component.yml in your preferred text editor and update its contents with:

Convert Image to Grayscale
language: py
platform: linux/amd64
build_system: 2
worker:
  input_type: "Image"
  output_type: "Image"

πŸ“ STEP 5: Add the source code to main.py

Open src/main.py in your preferred text editor and update its contents with:

from pipelogic.worker import run, config
import pipelogic
import numpy as np
import cppipe
import cv2

Image_BGR = cppipe.create_named('Image.BGR', cppipe.create_tuple([]))
Image_RGB = cppipe.create_named('Image.RGB', cppipe.create_tuple([]))
Image_GRAY = cppipe.create_named('Image.GRAY', cppipe.create_tuple([]))
Image_RGBA = cppipe.create_named('Image.RGBA', cppipe.create_tuple([]))
Image_BGRA = cppipe.create_named('Image.BGRA', cppipe.create_tuple([]))

# converts all possible image formats into gray image
def gray_conversion(Image):
    image_data = np.array(Image.data, dtype='uint8')
    if Image.format == Image_BGR:
    	 image = np.reshape(image_data, (Image.height, Image.width, 3))
         return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    elif Image.format == Image_RGB:
    	 image = np.reshape(image_data, (Image.height, Image.width, 3))
         return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    elif Image.format == Image_RGBA:
    	 image = np.reshape(image_data, (Image.height, Image.width, 4))
         return cv2.cvtColor(image, cv2.COLOR_RGBA2GRAY)
    elif Image.format == Image_BGRA:
    	 image = np.reshape(image_data, (Image.height, Image.width, 4))
         return cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
    else:
    	 image = np.reshape(image_data, (Image.height, Image.width, 1))
         return image	   

def convert_gray(Image):
    gray_image = gray_conversion(Image)

    return {
       "height": Image.height,
         "width": Image.width,
         "data": gray_image.flatten().tobytes(),
         "format": pipelogic.types.Named(pipelogic.types.Tuple(()), Image_GRAY)
    }
run(convert_gray)

🧱 Component Folder Structure

After you create a component, this is what the folder structure look like:

πŸ”Ή General Structure

.
β”œβ”€β”€ component.yml
β”œβ”€β”€ .pipecomponent
β”œβ”€β”€ src
β”‚   β”œβ”€β”€ requirements.txt
β”‚   └── main.py

To learn more about how this structure is generated and what each file means, visit the Component Guide page.

Example: Structure of a Custom Component Like Dot Product

Note: This is a custom example that shows what a complete component might look like, including test folders for validating input/output behavior.The dot product is used as an example because it takes two inputs (vectors) and produces one output (a scalar), which is a common pattern in many data processing components.Each test folder (test_0, test_1, etc.) includes input and expected output files. These tests can help you validate the component logic during development.

.
β”œβ”€β”€ component.yml
β”œβ”€β”€ .pipecomponent
β”œβ”€β”€ src
β”‚   β”œβ”€β”€ requirements.txt
β”‚   └── main.py
└── tests
    β”œβ”€β”€ test_0
    β”‚   β”œβ”€β”€ input_0.txt
    β”‚   β”œβ”€β”€ input_1.txt
    β”‚   └── output_0.txt
    └── test_1
        β”œβ”€β”€ input_0.txt
        β”œβ”€β”€ input_1.txt
        └── output_0.txt

Once your component structure looks like this and you've added your logic, you're ready to push it to the PipeLogic workspace.

  1. Make sure you're in the main folder:
cd convert_image_grayscale
  1. Login (only once):
ppl login
  1. Initialize the component:
ppl init
  1. Push your component:
ppl release

Add Parameters to Make Your Component Flexible


Now that you've successfully created your own component, you can make it dynamic by adding parameters. This allows users to customize its behavior directly from the UI without changing the code!

Why Add Parameters?

  • Make your component reusable for different inputs
  • Allow users to set values like resize_shape, crop coordinates, etc.
  • Improve user control and flexibility

βœ… 1. Define Parameters in component.yml

config_schema:
  resize_shape:
    type: (UInt64, UInt64)
    description: "Resize image to (height, width)"

This tells PipeLogic to show a UI field for resize_shape.

βœ… 2. Use the Parameter in Your Code (main.py)

resize_shape = config.resize_shape  # (height, width)
resized_image = cv2.resize(image, resize_shape)

βœ… 3. Release Your Component Again

ppl release

Example config_schema for multiple parameters

config_schema:
  resize_shape:
    type: (UInt64, UInt64)
  apply_blur:
    type: Bool
  blur_radius:
    type: UInt64

πŸ“ Important Notes

  • You can define as many parameters as needed
  • Each parameter must have a name and a type
  • Common types: String, UInt64, Float64, Bool, Tuple

πŸ‘‰ Click here to dive deeper into the Type System

Was this page helpful?