Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the Average Color within a Polygon Bound in OpenCV

Background

I am trying to create a utility that will return the average pixel color within a given polygon using OpenCV. The polygon will be defined via 4 points, but it is not necessarily a rectangle/square. For example, the following structures are to be expected:

     A__________B    A_______B
    /          /     \       \
   /          /       \       \
 D/__________/C       D\_______\C

Given a cv::Mat image in OpenCV and a polygon defined by the points (A, B, C, D). I know points A, B, C, and D, but I want to calc the average pixel color within the polygon. I wanted to get some suggestions from the OpenCV community on how to do this most efficiently.


Research Done

Another post on StackOverflow suggested drawing contours using the drawContours function and then take the mean of the bounding rectangle surrounding the contour. I would obviously have to modify the mean calculation so that it uses the polygons drawn by the fillPoly function instead.

Suggestions/Concerns are much appreciated!

like image 279
Jonathan Avatar asked Sep 08 '15 20:09

Jonathan


People also ask

How do you find the average RGB of an image in Python?

Use the average() Function of NumPy to Find the Average Color of Images in Python. In mathematics, we can find the average of a vector by dividing the sum of all the elements in the vector by the total number of elements.

How do you find the average RGB of an image?

The typical approach to averaging RGB colors is to add up all the red, green, and blue values, and divide each by the number of pixels to get the components of the final color. There's a better way! Instead of summing up the components of the RGB color, sum their squares instead.

What does cv2 fillPoly do?

fillPoly() function of OpenCV is used to draw filled polygons like rectangle, triangle, pentagon over an image. This function takes inputs an image and endpoints of Polygon and color.


1 Answers

You can simply use the mean function with a mask, where the mask is your filled polygon.

#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;

int main()
{
    // Create a black image with a gray rectangle on top left
    Mat1b img(300, 300, uchar(0));
    rectangle(img, Rect(0, 0, 100, 100), Scalar(100), CV_FILLED);

    // Define a polygon
    Point pts[1][4];
    pts[0][0] = Point(20, 20);
    pts[0][1] = Point(40, 100);
    pts[0][2] = Point(200, 60);
    pts[0][3] = Point(150, 30);

    const Point* points[1] = {pts[0]};
    int npoints = 4;

    // Create the mask with the polygon
    Mat1b mask(img.rows, img.cols, uchar(0));
    fillPoly(mask, points, &npoints, 1, Scalar(255));

    // Compute the mean with the computed mask
    Scalar average = mean(img, mask);

    std::cout << average << std::endl;

    return 0;
}
like image 150
Miki Avatar answered Nov 15 '22 17:11

Miki