{ "cells": [ { "cell_type": "markdown", "id": "3232eaf0", "metadata": {}, "source": [ "\n", "# Getting Started with Manufacturing Datasets\n", "\n", "Welcome to this hands-on workshop where we will learn how to load and explore datasets using FiftyOne. \n", "This notebook will guide you through programmatic interaction via the **FiftyOne SDK** and visualization using the **FiftyOne App**.\n", "\n", "![anomaly-load](https://cdn.voxel51.com/getting_started_manufacturing/notebook1/anomaly-load.webp)\n", "\n", "\n", "## Learning Objectives:\n", "- Load datasets into FiftyOne from different sources.\n", "- Understand the structure and metadata of datasets.\n", "- Use FiftyOne’s querying and filtering capabilities.\n", "- Interactively explore datasets in the FiftyOne App.\n", "\n", "In this example, we use Hugging Face Hub for dataset loading, but you are encouraged to explore other sources like local files, cloud storage, or custom dataset loaders.\n", "\n" ] }, { "cell_type": "markdown", "id": "2ad8719f", "metadata": {}, "source": [ "## In this notebook, we covered:\n", "1. Loading datasets from Hugging Face Hub (extendable to other sources).\n", "2. Exploring dataset structure and metadata.\n", "3. Applying filtering and querying techniques to analyze data.\n", "4. Utilizing the FiftyOne App for interactive visualization.\n", "5. Clone dataset views and export your Data in FiftyOne Format \n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Requirements and FiftyOne Installation\n", "\n", "First thing you need to do is create a Python environment in your system, if you are not familiar with that please take a look of this [ReadmeFile](https://github.com/voxel51/fiftyone-examples?tab=readme-ov-file#-prerequisites-for-beginners-), where we will explain how to create the environment. After that be sure you activate the created environment and install FiftyOne there." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Install FiftyOne" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install fiftyone huggingface_hub gdown" ] }, { "cell_type": "markdown", "id": "4ee1b1c2", "metadata": {}, "source": [ "\n", "## Loading a Dataset into FiftyOne\n", "\n", "FiftyOne provides multiple ways to import datasets, including:\n", "- **Hugging Face Hub** (as demonstrated here)\n", "- **Local files** (images, videos, or annotations in JSON, COCO, PASCAL VOC, etc.)\n", "- **Cloud storage** (AWS S3, Google Drive, etc.) - Just for FiftyOne Enterprise\n", "\n", "To load a dataset, we specify the source and format, ensuring FiftyOne properly indexes the data.\n", "\n", "**Relevant Documentation:** [Dataset Importing in FiftyOne](https://voxel51.com/docs/fiftyone/user_guide/dataset_creation/index.html)\n", "\n", "We are using [MVTec AD Dataset](https://www.mvtec.com/company/research/datasets/mvtec-ad) from [Voxel51 Hugging Face Hub](https://huggingface.co/datasets/Voxel51/mvtec-ad). The difference between the original resource and the Voxel51's one is the data structure, while in the first one we have a tree directory with category,in the second one we have an unstructure dataset with metadata such as ```categories.label```, and ```defect.label```.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import fiftyone as fo # base library and app\n", "import fiftyone.utils.huggingface as fouh # Hugging Face integration\n", "\n", "dataset_name = \"MVTec_AD\"\n", "\n", "# Check if the dataset exists\n", "if dataset_name in fo.list_datasets():\n", " print(f\"Dataset '{dataset_name}' exists. Loading...\")\n", " dataset = fo.load_dataset(dataset_name)\n", "else:\n", " print(f\"Dataset '{dataset_name}' does not exist. Creating a new one...\")\n", " # Clone the dataset with a new name and make it persistent\n", " dataset_ = fouh.load_from_hub(\"Voxel51/mvtec-ad\", persistent=True, overwrite=True)\n", " dataset = dataset_.clone(\"MVTec_AD\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Alternative - Download from Google Drive\n", "\n", "If you find any issues downloading the dataset from Hugging Face, please uncomment and use the following code cell." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# import gdown\n", "\n", "# # Download the coffee dataset from Google Drive\n", "\n", "# url = \"https://drive.google.com/uc?id=1nAuFIyl2kM-TQXduSJ9Fe_ZEIVog4tth\" # original\n", "# gdown.download(url, output=\"mvtec-ad.zip\", quiet=False)\n", "# !unzip mvtec-ad.zip\n", "\n", "# import fiftyone as fo\n", "\n", "# dataset_viz =fo.Dataset.from_dir(\n", "# dataset_dir=\"/content/mvtec-ad\",\n", "# dataset_type=fo.types.FiftyOneDataset,\n", "# name = \"MVTec_AD\",\n", "# )" ] }, { "cell_type": "markdown", "id": "a13ff8a6", "metadata": {}, "source": [ "\n", "## Exploring the Dataset\n", "\n", "Once the dataset is loaded, we can inspect its structure using FiftyOne’s SDK.\n", "We will explore:\n", "- The number of samples in the dataset.\n", "- Available metadata and labels.\n", "- How images/videos are structured.\n", "\n", " **Relevant Documentation:** [Inspecting Datasets in FiftyOne](https://docs.voxel51.com/user_guide/using_datasets.html#using-fiftyone-datasets) You can also call the [first Sample](https://docs.voxel51.com/api/fiftyone.core.dataset.html#fiftyone.core.dataset.Dataset.first) of the Dataset to see what the Fields looks like:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(dataset)\n", "print(dataset.first()) # Inspect the first or last sample" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "session = fo.launch_app(dataset, auto=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![exploring_dataset](https://cdn.voxel51.com/getting_started_manufacturing/notebook1/exploring_dataset.webp)\n" ] }, { "cell_type": "markdown", "id": "b2f27130", "metadata": {}, "source": [ "\n", "## Querying and Filtering\n", "\n", "FiftyOne provides a powerful querying engine to filter and analyze datasets efficiently.\n", "We can apply filters to:\n", "- Retrieve specific labels (e.g., all images with \"cat\" labels).\n", "- Apply confidence thresholds to object detections.\n", "- Filter data based on metadata (e.g., image size, timestamp).\n", "\n", "**Relevant Documentation:** [Dataset views](https://docs.voxel51.com/user_guide/using_views.html#dataset-views), [Querying Samples](https://docs.voxel51.com/user_guide/using_views.html#querying-samples), [Common filters](https://docs.voxel51.com/user_guide/using_views.html#querying-samples)\n", "\n", "### Examples:\n", "- Show all images containing a particular class.\n", "- Retrieve samples with object detection confidence above a threshold.\n", "- Filter out low-quality images based on metadata.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import fiftyone.core.expressions as foe\n", "# Query images where the defect is labeled as \"scratch\"\n", "view = dataset.match(foe.ViewField(\"defect.label\") == \"scratch\")\n", "print(view)\n", "\n", "# Launch FiftyOne App with the filtered dataset\n", "session = fo.launch_app(view, port=5151, auto=False)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![querying_filtering](https://cdn.voxel51.com/getting_started_manufacturing/notebook1/querying_filtering.webp)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "filter = view.match(foe.ViewField(\"category.label\") == \"wood\")\n", "session.view = filter\n", "print(filter)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Launch FiftyOne App with the filtered dataset\n", "session = fo.launch_app(filter, port=5151, auto=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![filtering](https://cdn.voxel51.com/getting_started_manufacturing/notebook1/filtering.webp)\n" ] }, { "cell_type": "markdown", "id": "7a0766d0", "metadata": {}, "source": [ "\n", "## Interactive Exploration with the FiftyOne App\n", "\n", "The **FiftyOne App** allows users to interactively browse, filter, and analyze datasets.\n", "This visual interface is an essential tool for understanding dataset composition and refining data exploration workflows.\n", "\n", "Key features of the FiftyOne App:\n", "- Interactive filtering of images/videos.\n", "- Object detection visualization.\n", "- Dataset statistics and metadata overview.\n", "\n", "**Relevant Documentation:** [Using the FiftyOne App](https://voxel51.com/docs/fiftyone/user_guide/app.html)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Intereacting with Plugins to understand the dataset\n", "\n", "FiftyOne provides a powerful [plugin framework](https://docs.voxel51.com/plugins/index.html) that allows for extending and customizing the functionality of the tool to suit your specific needs. In this case we will use the [@voxel51/dashboard](https://github.com/voxel51/fiftyone-plugins/blob/main/plugins/dashboard/README.md) plugin, a plugin that enables users to construct custom dashboards that display statistics of interest about the current dataset (and beyond)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#!fiftyone plugins download https://github.com/voxel51/fiftyone-plugins --plugin-names @voxel51/dashboard" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![exploration_app](https://cdn.voxel51.com/getting_started_manufacturing/notebook1/exploration_app.webp)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## New dataset\n", "\n", "Creates a new dataset containing a copy of the contents of the view." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "new_dataset= view.clone()\n", "print(new_dataset)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exporting Dataset to FiftyOneDataset\n", "\n", "FiftyOne supports various dataset formats. In this notebook, we’ve worked with a custom dataset from Hugging Face Hub. Now, we export it into a FiftyOne-compatible dataset to leverage additional capabilities.\n", "\n", "For more details on the dataset types supported by FiftyOne, refer to this [documentation](https://docs.voxel51.com/api/fiftyone.types.dataset_types.html?highlight=dataset%20type#module-fiftyone.types.dataset_types)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "export_dir = \"MVTec_scratch\"\n", "new_dataset.export(\n", " export_dir=export_dir,\n", " dataset_type=fo.types.FiftyOneDataset,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Next Steps:\n", "Try modifying the dataset loading parameters, apply different filters, and explore the FiftyOne App’s visualization features! 🚀" ] } ], "metadata": { "kernelspec": { "display_name": "manu_env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.17" } }, "nbformat": 4, "nbformat_minor": 2 }