🐶
Machine Vision

OpenCV C++/Obj-C: Sheet of Paper and Square Detection

By Jan on 02/17/2025

Learn how to detect a sheet of paper or squares in images using OpenCV with C++ and Objective-C, covering edge detection, contour finding, and geometric shape recognition techniques.

OpenCV C++/Obj-C: Sheet of Paper and Square Detection

Table of Contents

Introduction

This document outlines the steps involved in detecting a sheet of paper in an image using OpenCV, a popular computer vision library. The process involves loading the image, converting it to grayscale, applying Gaussian blur to reduce noise, and then detecting edges using the Canny edge detection algorithm. Contours are then extracted from the edge image, and those that meet specific criteria for area and approximate shape (four sides) are identified as potential paper sheets. The final step, which is optional, involves extracting the detected paper sheet from the image using perspective transformation.

Step-by-Step Guide

  1. Load the image:

    cv::Mat image = cv::imread("path/to/image.jpg");
  2. Convert to grayscale:

    cv::Mat gray;
    cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
  3. Apply Gaussian blur:

    cv::GaussianBlur(gray, gray, cv::Size(5, 5), 0);
  4. Detect edges:

    cv::Mat edges;
    cv::Canny(gray, edges, 50, 150);
  5. Find contours:

    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
  6. Filter contours by area and approximate shape:

    for (const auto &contour : contours) {
        double area = cv::contourArea(contour);
        if (area > 1000) {
            std::vector<cv::Point> approx;
            cv::approxPolyDP(contour, approx, 0.02 * cv::arcLength(contour, true), true);
            if (approx.size() == 4) {
                // Found a potential square/rectangle
            }
        }
    }
  7. (Optional) Extract the paper sheet:

    • Find the corners of the detected square/rectangle.
    • Use cv::getPerspectiveTransform to get a transformation matrix.
    • Apply cv::warpPerspective to warp the image and extract the paper sheet.

Code Example

This C++ code uses OpenCV to detect a potential paper sheet in an image. It loads an image, converts it to grayscale, applies Gaussian blur, and detects edges. Then, it finds contours in the edge image and filters them by area. If a contour is large enough and has approximately four sides, it's considered a potential paper sheet. The code provides a guide for extracting the paper sheet using perspective transformation, but the implementation details are left to the user.

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 1. Load the image
    cv::Mat image = cv::imread("path/to/image.jpg");
    if (image.empty()) {
        std::cerr << "Could not read the image!" << std::endl;
        return -1;
    }

    // 2. Convert to grayscale
    cv::Mat gray;
    cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

    // 3. Apply Gaussian blur
    cv::GaussianBlur(gray, gray, cv::Size(5, 5), 0);

    // 4. Detect edges
    cv::Mat edges;
    cv::Canny(gray, edges, 50, 150);

    // 5. Find contours
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    // 6. Filter contours by area and approximate shape
    for (const auto &contour : contours) {
        double area = cv::contourArea(contour);
        if (area > 1000) {
            std::vector<cv::Point> approx;
            cv::approxPolyDP(contour, approx, 0.02 * cv::arcLength(contour, true), true);
            if (approx.size() == 4) {
                // Found a potential square/rectangle
                std::cout << "Found a potential paper sheet!" << std::endl;

                // 7. (Optional) Extract the paper sheet
                // Find the corners of the detected square/rectangle
                // (Implementation depends on the desired corner order)

                // Use cv::getPerspectiveTransform to get a transformation matrix
                // cv::Mat transform = cv::getPerspectiveTransform(src_corners, dst_corners);

                // Apply cv::warpPerspective to warp the image and extract the paper sheet
                // cv::Mat warped;
                // cv::warpPerspective(image, warped, transform, warped.size());
            }
        }
    }

    // Display the results (optional)
    cv::imshow("Original Image", image);
    cv::imshow("Edges", edges);
    cv::waitKey(0);

    return 0;
}

Explanation:

  1. Include headers: Include necessary headers for OpenCV.
  2. Load image: Load the image using cv::imread.
  3. Convert to grayscale: Convert the image to grayscale using cv::cvtColor.
  4. Apply Gaussian blur: Apply Gaussian blur to reduce noise using cv::GaussianBlur.
  5. Detect edges: Detect edges in the image using the Canny edge detector (cv::Canny).
  6. Find contours: Find contours in the edge image using cv::findContours.
  7. Filter contours:
    • Iterate through each contour.
    • Calculate the contour area using cv::contourArea.
    • If the area is above a threshold (1000 in this case), approximate the contour shape using cv::approxPolyDP.
    • If the approximated shape has 4 sides (potential square/rectangle), you've likely found the paper sheet.
  8. (Optional) Extract paper sheet:
    • This part is left as a general guide because the implementation of finding corners and the desired order of corners for perspective transformation depend on the specific use case.
    • Use cv::getPerspectiveTransform to calculate the transformation matrix based on the source and destination corner points.
    • Apply cv::warpPerspective to warp the original image using the calculated transformation matrix, effectively extracting the paper sheet.

Remember to:

  • Replace "path/to/image.jpg" with the actual path to your image.
  • Adjust the parameters for Canny edge detection, contour area threshold, and cv::approxPolyDP based on your image and desired results.
  • Implement the corner finding and perspective transformation logic according to your specific needs in the optional paper sheet extraction step.

Additional Notes

  • Image preprocessing: Converting the image to grayscale and applying Gaussian blur are crucial preprocessing steps. Grayscale conversion simplifies the image data, while Gaussian blur reduces noise, making edge detection more accurate.

  • Canny edge detection parameters: The Canny(gray, edges, 50, 150) function uses two threshold values (50 and 150 in this case). These thresholds determine the sensitivity of edge detection. Experiment with different values to fine-tune the results for your specific images.

  • Contour retrieval mode: cv::RETR_EXTERNAL retrieves only the outermost contours, which is suitable for detecting the paper sheet's boundary. Other modes like cv::RETR_LIST or cv::RETR_TREE can be used if you need to detect contours within contours.

  • Contour approximation method: cv::CHAIN_APPROX_SIMPLE compresses the contour representation by storing only essential points. This reduces memory usage and speeds up processing.

  • Area threshold: The area > 1000 condition filters out small contours that are unlikely to represent the paper sheet. Adjust this threshold based on the expected size of the paper sheet in your images.

  • Polygon approximation: cv::approxPolyDP approximates the contour with a polygon. The 0.02 * cv::arcLength(contour, true) parameter controls the accuracy of the approximation. A smaller value results in a more accurate but potentially more complex polygon.

  • Corner finding: The comment "// Find the corners of the detected square/rectangle" highlights an important step. You can use various techniques to find the corners, such as:

    • Finding the convex hull of the contour and selecting the four extreme points.
    • Using the cv::cornerHarris or cv::goodFeaturesToTrack functions to detect corners in the image.
  • Perspective transformation: cv::getPerspectiveTransform calculates the transformation matrix based on the correspondence between the four corners of the detected paper sheet in the original image and the desired output coordinates. cv::warpPerspective then applies this transformation to extract and rectify the paper sheet.

  • Error handling: The code includes a check for successful image loading (if (image.empty())). It's good practice to add similar checks for other OpenCV functions that might fail.

  • Displaying results: The code uses cv::imshow to display the original image and the edge image. This is helpful for visualizing the intermediate steps and debugging the code.

  • Real-world considerations: In real-world scenarios, you might encounter images with varying lighting conditions, backgrounds, and paper sheet orientations. Consider using techniques like adaptive thresholding, background subtraction, or Hough transform to improve the robustness of your paper sheet detection algorithm.

Summary

This code snippet outlines the steps to detect and potentially extract a rectangular paper sheet from an image using OpenCV in C++.

1. Preprocessing:

  • The image is loaded and converted to grayscale for easier processing.
  • Gaussian blur is applied to reduce noise and smooth out the image.

2. Edge Detection and Contour Finding:

  • The Canny edge detector identifies sharp edges in the image.
  • Contours (connected points representing boundaries) are extracted from the edge map.

3. Filtering Contours:

  • Contours are filtered based on their area to eliminate small, insignificant shapes.
  • The remaining contours are approximated to polygons.
  • Contours with four sides (potential squares/rectangles) are identified.

4. (Optional) Paper Sheet Extraction:

  • If a suitable four-sided contour is found, its corners can be used to calculate a perspective transformation matrix.
  • This matrix can then be used to warp the original image, effectively extracting and straightening the detected paper sheet.

In essence, this code leverages edge detection and contour analysis to locate a rectangular shape within an image, which could represent a paper sheet. It also provides a method for isolating and potentially straightening this detected region.

Conclusion

This code demonstrates a fundamental process in computer vision: detecting specific shapes within images. By converting the image to grayscale, applying a Gaussian blur, and using Canny edge detection, the code effectively highlights the edges within the image. Finding contours based on these edges and filtering them based on area and approximation allows for the identification of potential rectangular shapes, which could represent a sheet of paper. The optional step of extracting the paper sheet using perspective transformation further showcases how image processing techniques can be used to isolate and manipulate specific regions of interest within images. This example provides a practical illustration of how OpenCV can be employed for tasks ranging from document scanning to object detection.

References

Were You Able to Follow the Instructions?

😍Love it!
😊Yes
😐Meh-gical
😞No
🤮Clickbait