From 22a49ccf9293b9e7230a6b1aea9280b7aef53607 Mon Sep 17 00:00:00 2001 From: Aditya Singh <155234975+adityasingh-0803@users.noreply.github.com> Date: Sun, 5 Jan 2025 19:07:24 +0530 Subject: [PATCH 1/3] Add files via upload This is image extraction code ocr --- docs/ML/projects/OCR.ipynb | 483 ++++++++++++++++++ .../quotes-about-life-love-yourself.jpg | Bin 0 -> 37894 bytes 2 files changed, 483 insertions(+) create mode 100644 docs/ML/projects/OCR.ipynb create mode 100644 docs/ML/projects/quotes-about-life-love-yourself.jpg diff --git a/docs/ML/projects/OCR.ipynb b/docs/ML/projects/OCR.ipynb new file mode 100644 index 00000000..b95cb24f --- /dev/null +++ b/docs/ML/projects/OCR.ipynb @@ -0,0 +1,483 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "_I13dfVEjVZ5" + }, + "source": [ + "\n", + "\n", + "```\n", + "# This is formatted as code\n", + "```\n", + "\n", + "# Optical Character Recognition using Tesseract" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ydvTlknjrAHU" + }, + "source": [ + "# By Aditya Singh\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "wpWkMPfNj66y" + }, + "source": [ + "Optical Character Recognition(OCR) has been a popular task in Computer Vision. Tesseract is the most open-source software available for OCR. It was initially developed by HP as a tool in C++.\n", + "Since 2006 it is developed by Google. The original software is available as a command-line tool for windows. We are living in a python world. Because of its popularity,the tool is also available in python--developed and maintained as an opensource project." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GDZYVGrJkorH" + }, + "source": [ + "### Step1. Install Pytesseract and tesseract-OCR in Google Colab." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "uWwpI-24_Nob", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "553cd595-0a23-4026-afb4-bb1139d66dec" + }, + "source": [ + "!sudo apt install tesseract-ocr" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Reading package lists... Done\n", + "Building dependency tree... Done\n", + "Reading state information... Done\n", + "The following additional packages will be installed:\n", + " tesseract-ocr-eng tesseract-ocr-osd\n", + "The following NEW packages will be installed:\n", + " tesseract-ocr tesseract-ocr-eng tesseract-ocr-osd\n", + "0 upgraded, 3 newly installed, 0 to remove and 49 not upgraded.\n", + "Need to get 4,816 kB of archives.\n", + "After this operation, 15.6 MB of additional disk space will be used.\n", + "Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 tesseract-ocr-eng all 1:4.00~git30-7274cfa-1.1 [1,591 kB]\n", + "Get:2 http://archive.ubuntu.com/ubuntu jammy/universe amd64 tesseract-ocr-osd all 1:4.00~git30-7274cfa-1.1 [2,990 kB]\n", + "Get:3 http://archive.ubuntu.com/ubuntu jammy/universe amd64 tesseract-ocr amd64 4.1.1-2.1build1 [236 kB]\n", + "Fetched 4,816 kB in 2s (2,904 kB/s)\n", + "debconf: unable to initialize frontend: Dialog\n", + "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 78, <> line 3.)\n", + "debconf: falling back to frontend: Readline\n", + "debconf: unable to initialize frontend: Readline\n", + "debconf: (This frontend requires a controlling tty.)\n", + "debconf: falling back to frontend: Teletype\n", + "dpkg-preconfigure: unable to re-open stdin: \n", + "Selecting previously unselected package tesseract-ocr-eng.\n", + "(Reading database ... 123614 files and directories currently installed.)\n", + "Preparing to unpack .../tesseract-ocr-eng_1%3a4.00~git30-7274cfa-1.1_all.deb ...\n", + "Unpacking tesseract-ocr-eng (1:4.00~git30-7274cfa-1.1) ...\n", + "Selecting previously unselected package tesseract-ocr-osd.\n", + "Preparing to unpack .../tesseract-ocr-osd_1%3a4.00~git30-7274cfa-1.1_all.deb ...\n", + "Unpacking tesseract-ocr-osd (1:4.00~git30-7274cfa-1.1) ...\n", + "Selecting previously unselected package tesseract-ocr.\n", + "Preparing to unpack .../tesseract-ocr_4.1.1-2.1build1_amd64.deb ...\n", + "Unpacking tesseract-ocr (4.1.1-2.1build1) ...\n", + "Setting up tesseract-ocr-eng (1:4.00~git30-7274cfa-1.1) ...\n", + "Setting up tesseract-ocr-osd (1:4.00~git30-7274cfa-1.1) ...\n", + "Setting up tesseract-ocr (4.1.1-2.1build1) ...\n", + "Processing triggers for man-db (2.10.2-1) ...\n" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "ujL16dZ2_O-3", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "781a1fc8-5b33-4e9f-fcca-6718dea17723" + }, + "source": [ + "!pip install pytesseract" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Collecting pytesseract\n", + " Downloading pytesseract-0.3.13-py3-none-any.whl.metadata (11 kB)\n", + "Requirement already satisfied: packaging>=21.3 in /usr/local/lib/python3.10/dist-packages (from pytesseract) (24.1)\n", + "Requirement already satisfied: Pillow>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from pytesseract) (10.4.0)\n", + "Downloading pytesseract-0.3.13-py3-none-any.whl (14 kB)\n", + "Installing collected packages: pytesseract\n", + "Successfully installed pytesseract-0.3.13\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zlsiJdwnkyx7" + }, + "source": [ + "### Step2. import libraries" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "QKJh7JjTAqzO" + }, + "source": [ + "import pytesseract\n", + "import shutil\n", + "import os\n", + "import random\n", + "try:\n", + " from PIL import Image\n", + "except ImportError:\n", + " import Image" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yjaf9bJ3k4GC" + }, + "source": [ + "### Step3. Upload Image to the Colab" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "8zmc-K_nAyg1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 73 + }, + "outputId": "b60c904c-7496-4e8f-e964-80dff99843ef" + }, + "source": [ + "from google.colab import files\n", + "\n", + "uploaded = files.upload()" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + " \n", + " \n", + " Upload widget is only available when the cell has been executed in the\n", + " current browser session. Please rerun this cell to enable.\n", + " \n", + " " + ] + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Saving quotes-about-life-love-yourself.jpg to quotes-about-life-love-yourself.jpg\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MDdbltgIlF3Q" + }, + "source": [ + "## Step4. Text Extraction" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "HaM3cMUDA_Ma" + }, + "source": [ + "import pytesseract\n", + "import shutil\n", + "import os\n", + "import random\n", + "try:\n", + " from PIL import Image\n", + "except ImportError:\n", + " import Image\n", + "import requests\n", + "from io import BytesIO\n", + "\n", + "# Fetch the image from the URL\n", + "response = requests.get('https://becomingunbusy.com/wp-content/uploads/2019/05/quotes-about-life-love-yourself.jpg', stream=True)\n", + "response.raw.decode_content = True # Ensure correct decoding\n", + "\n", + "# Open the image using BytesIO to handle the image data\n", + "image = Image.open(BytesIO(response.content))\n", + "\n", + "# Now you can use pytesseract to extract text\n", + "extractedInformation = pytesseract.image_to_string(image)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "D552cuoflHvx" + }, + "source": [ + "### Step5. Printing the extracted information" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Key-3vILBNUd", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "f87373b9-2b31-4f2c-9e7f-efbe451e37e9" + }, + "source": [ + "print(extractedInformation)" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "KAMEN ARIE NA I\n", + "love yourself enough to no longer\n", + "\n", + "just dream of a better life, let it be the day\n", + "\n", + "TONE Hae\n", + "\n", + " \n", + "\f\n" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/ML/projects/quotes-about-life-love-yourself.jpg b/docs/ML/projects/quotes-about-life-love-yourself.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e89cdcef08543a19d9791a7cd09bac6f6f895524 GIT binary patch literal 37894 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 Date: Sun, 26 Jan 2025 19:20:10 +0530 Subject: [PATCH 2/3] Readme.md --- product detection/Readme.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 product detection/Readme.md diff --git a/product detection/Readme.md b/product detection/Readme.md new file mode 100644 index 00000000..a5db9e20 --- /dev/null +++ b/product detection/Readme.md @@ -0,0 +1,27 @@ +# Product Detection + +## Overview +This repository provides a solution for product detection using machine learning and computer vision techniques. The project leverages deep learning models to detect and classify products from images or video streams. It is suitable for applications in inventory management, retail analytics, and e-commerce. + +## Features +- **Product Detection**: Identifies and locates products within images and videos. +- **Product Classification**: Classifies detected products based on pre-trained models. +- **Real-Time Processing**: Supports real-time video processing for dynamic environments. +- **Customizable**: Allows fine-tuning to specific product datasets and use cases. + +## Requirements +- Python 3.x +- OpenCV +- TensorFlow or PyTorch (depending on model used) +- Other dependencies listed in `requirements.txt` + +## Installation + +Follow these steps to get started with the project. + +1. Clone the repository to your local machine: + ```bash + git clone https://github.com/username/product-detection.git + cd product-detection + +2. pip install -r requirements.txt From bd5e85bf6fb7b20b52ca8fc28d79c59bbaa29281 Mon Sep 17 00:00:00 2001 From: Aditya Singh <155234975+adityasingh-0803@users.noreply.github.com> Date: Sun, 26 Jan 2025 19:20:39 +0530 Subject: [PATCH 3/3] Add files via upload --- product detection/Product_Detection.ipynb | 389 ++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 product detection/Product_Detection.ipynb diff --git a/product detection/Product_Detection.ipynb b/product detection/Product_Detection.ipynb new file mode 100644 index 00000000..64b654df --- /dev/null +++ b/product detection/Product_Detection.ipynb @@ -0,0 +1,389 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "code", + "source": [ + "# Install the required dependencies\n", + "!pip install opencv-python opencv-python-headless\n", + "\n", + "# Download the YOLOv3 pre-trained model weights\n", + "!wget https://pjreddie.com/media/files/yolov3.weights\n", + "!wget https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg\n", + "!wget https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "jKona4B6ng4V", + "outputId": "b043c4c6-147e-4dda-e7d1-5b30c3833ba2" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Requirement already satisfied: opencv-python in /usr/local/lib/python3.11/dist-packages (4.10.0.84)\n", + "Requirement already satisfied: opencv-python-headless in /usr/local/lib/python3.11/dist-packages (4.10.0.84)\n", + "Requirement already satisfied: numpy>=1.21.2 in /usr/local/lib/python3.11/dist-packages (from opencv-python) (1.26.4)\n", + "--2025-01-16 06:20:16-- https://pjreddie.com/media/files/yolov3.weights\n", + "Resolving pjreddie.com (pjreddie.com)... 162.0.215.52\n", + "Connecting to pjreddie.com (pjreddie.com)|162.0.215.52|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 248007048 (237M) [application/octet-stream]\n", + "Saving to: ‘yolov3.weights’\n", + "\n", + "yolov3.weights 100%[===================>] 236.52M 12.3MB/s in 18s \n", + "\n", + "2025-01-16 06:20:35 (12.9 MB/s) - ‘yolov3.weights’ saved [248007048/248007048]\n", + "\n", + "--2025-01-16 06:20:35-- https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg\n", + "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.109.133, ...\n", + "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 8342 (8.1K) [text/plain]\n", + "Saving to: ‘yolov3.cfg’\n", + "\n", + "yolov3.cfg 100%[===================>] 8.15K --.-KB/s in 0s \n", + "\n", + "2025-01-16 06:20:35 (58.2 MB/s) - ‘yolov3.cfg’ saved [8342/8342]\n", + "\n", + "--2025-01-16 06:20:35-- https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names\n", + "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n", + "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 625 [text/plain]\n", + "Saving to: ‘coco.names’\n", + "\n", + "coco.names 100%[===================>] 625 --.-KB/s in 0s \n", + "\n", + "2025-01-16 06:20:35 (28.8 MB/s) - ‘coco.names’ saved [625/625]\n", + "\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import cv2\n", + "import numpy as np\n", + "\n", + "# Load YOLO model\n", + "net = cv2.dnn.readNet(\"yolov3.weights\", \"yolov3.cfg\")\n", + "layer_names = net.getLayerNames()\n", + "output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]\n", + "\n", + "# Load class labels (from coco.names)\n", + "with open(\"coco.names\", \"r\") as f:\n", + " classes = [line.strip() for line in f.readlines()]\n", + "\n", + "# Function to perform object detection\n", + "def detect_objects(image_path):\n", + " # Load image\n", + " img = cv2.imread(image_path)\n", + " height, width, channels = img.shape\n", + "\n", + " # Prepare the image for YOLO\n", + " blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)\n", + " net.setInput(blob)\n", + " outputs = net.forward(output_layers)\n", + "\n", + " # Initialize lists for detected objects\n", + " class_ids = []\n", + " confidences = []\n", + " boxes = []\n", + "\n", + " # Iterate over all detections\n", + " for out in outputs:\n", + " for detection in out:\n", + " scores = detection[5:]\n", + " class_id = np.argmax(scores)\n", + " confidence = scores[class_id]\n", + "\n", + " if confidence > 0.5: # Confidence threshold\n", + " center_x = int(detection[0] * width)\n", + " center_y = int(detection[1] * height)\n", + " w = int(detection[2] * width)\n", + " h = int(detection[3] * height)\n", + "\n", + " # Coordinates for the bounding box\n", + " x = int(center_x - w / 2)\n", + " y = int(center_y - h / 2)\n", + "\n", + " # Save the detection details\n", + " boxes.append([x, y, w, h])\n", + " confidences.append(float(confidence))\n", + " class_ids.append(class_id)\n", + "\n", + " # Apply non-maxima suppression to remove overlapping boxes\n", + " indexes = cv2.dnn.NMSBoxes(boxes, confidences, score_threshold=0.5, nms_threshold=0.4)\n", + "\n", + " # Draw the bounding boxes and labels\n", + " detected_objects = []\n", + " if len(indexes) > 0:\n", + " for i in indexes.flatten():\n", + " x, y, w, h = boxes[i]\n", + " label = str(classes[class_ids[i]])\n", + " confidence = confidences[i]\n", + " detected_objects.append((label, confidence))\n", + " cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)\n", + " cv2.putText(img, f\"{label} {confidence:.2f}\", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)\n", + "\n", + " return img, detected_objects\n", + "\n", + "# Display results\n", + "from google.colab import files\n", + "from IPython.display import Image\n", + "\n", + "# Upload an image\n", + "uploaded = files.upload()\n", + "\n", + "# Get image path\n", + "image_path = list(uploaded.keys())[0]\n", + "\n", + "# Run detection\n", + "result_img, detected_objects = detect_objects(image_path)\n", + "\n", + "# Save and display the result\n", + "output_path = \"result.jpg\"\n", + "cv2.imwrite(output_path, result_img)\n", + "Image(output_path)\n", + "\n", + "# Print detected objects and confidence\n", + "print(\"Detected Objects and Confidence Scores:\")\n", + "for label, confidence in detected_objects:\n", + " print(f\"{label}: {confidence:.2f}\")\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 108 + }, + "id": "P1krlvdqnv19", + "outputId": "7a7b00d2-e6c8-49cc-bbc3-13a003e9850c" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + " \n", + " \n", + " Upload widget is only available when the cell has been executed in the\n", + " current browser session. Please rerun this cell to enable.\n", + " \n", + " " + ] + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Saving Screenshot 2024-12-24 112646.png to Screenshot 2024-12-24 112646.png\n", + "Detected Objects and Confidence Scores:\n", + "bird: 0.98\n" + ] + } + ] + } + ] +} \ No newline at end of file