Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Count number of colored objects in image

Hi,

I am detecting multiple objects of different color from a video stream. I would like to count how many objects of each color appear in the stream. I am using OpenCV 2.4.8 on Ubuntu 14.04. Here is the code:

#!/usr/bin/env python
import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])

    # define range of red color in HSV
    lower_red = np.array([160, 100, 100])
    upper_red = np.array([179, 255, 255])

    # Threshold the HSV image to get only blue colors
    blue_mask = cv2.inRange(hsv, lower_blue, upper_blue)

    # Threshold the HSV image to get only red colors
    red_mask = cv2.inRange(hsv, lower_red, upper_red)

    # add the masks
    mask = red_mask + blue_mask

    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame, frame, mask = mask)

    # cv2.imshow('frame',frame)
    # cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

Attached is an image from the video stream. In that image there are 4 red boxes and 4 blue boxes which I would like to count.

Any help is appreciated. Thanks.C:\fakepath\image.png

Count number of colored objects in image

****** EDIT-1 *******

Sorry for the delayed response. Being new to OpenCV I did some research and found out that a connected components function was introduced in OpenCV 3.0 and it is only available in C++ (AFAIK) as shown here. So, I decided to to write my code in C++. I have also updated the test image (I would like to make it work on this before I got to video stream). Here is my code:

#include <iostream>
#include <vector>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;

// function to print type of mat
string type2str(int type) {
  string r;

  uchar depth = type & CV_MAT_DEPTH_MASK;
  uchar chans = 1 + (type >> CV_CN_SHIFT);

  switch ( depth ) {
    case CV_8U:  r = "8U"; break;
    case CV_8S:  r = "8S"; break;
    case CV_16U: r = "16U"; break;
    case CV_16S: r = "16S"; break;
    case CV_32S: r = "32S"; break;
    case CV_32F: r = "32F"; break;
    case CV_64F: r = "64F"; break;
    default:     r = "User"; break;
  }

  r += "C";
  r += (chans+'0');

  return r;
}

cv::Mat connect_components(cv::Mat img, int threshval)
{
    cv::Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
    cv::Mat labelImage(img.size(), CV_8S);
    auto nLabels = cv::connectedComponents(bw, labelImage, 8);
    vector<cv::Vec3b> colors(nLabels);
    colors[0] = cv::Vec3b(0, 0, 0); //background
    for(auto label = 1; label < nLabels; ++label){
        colors[label] = cv::Vec3b(255, 255, 255);
    }
    cv::Mat dst(img.size(), CV_8UC3);
    for(auto r = 0; r < dst.rows; ++r){
        for(auto c = 0; c < dst.cols; ++c){
            auto label = labelImage.at<int>(r, c);
            cv::Vec3b &pixel = dst.at<cv::Vec3b>(r, c);
            pixel = colors[label];
        }
    }

    return dst;
}

int main(int argc, char **argv)
{
    cv::VideoCapture webcam(0);

    if (!webcam.isOpened()) {
        cerr << "Cannot open webcam" << endl;
        exit(-1);
    }

    // Define range for blue and red color in HSV
    const cv::Scalar blue_range[] = { {110, 50, 50}, {130, 255, 255} };
    const cv::Scalar red_range[] = { {0, 200, 50}, {10, 255, 150} };

    cout << CV_MAJOR_VERSION << ", " << CV_MINOR_VERSION << endl;

    cv::Mat original_frame, color_mask[2], final_mask;
    while (true) {
        try {
            webcam.read(original_frame); // grab each frame
            cout << type2str(original_frame.type()) << endl;
            cv::Mat frame_hsv;
            cv::cvtColor(original_frame, frame_hsv, CV_BGR2HSV); // convert BGR to HSV

            // threshold HSV image to get only defined range colors
            cv::inRange(frame_hsv, blue_range[0], blue_range[1], color_mask[0]); 
            cv::inRange(frame_hsv, red_range[0], red_range[1], color_mask[1]);

            // add the masks
            final_mask = color_mask[0] + color_mask[1];

            // Bitwise-AND full mask and original image
            cv::Mat colored_boxes;
            cv::bitwise_and(original_frame, original_frame, colored_boxes, final_mask);

            // Apply morphological closing
            cv::Mat morphed_boxes;
            cv::morphologyEx(colored_boxes, morphed_boxes, cv::MORPH_CLOSE, cv::Mat::ones(10, 10, CV_8UC1));

            // Connected componenets
            auto labeled_boxes = connect_components(colored_boxes, 62);

            // Display the image
            //cv::imshow("Webcam", original_frame);
            cv::imshow("Boxes", morphed_boxes);

            // quit progrem is user inputs ESC or q
            auto user_input = (cv::waitKey(5) & 0xFF);
            if ((user_input == 27) || (user_input == 113)) {
                break;
            }
        }
        catch (cv::Exception &e) {
            cout << "Exception caught" << endl;
            cout << e.what();
            break;
        }
    }

    return 0;
}

The connected_components function is adopted from here.

When I run this, I get the following exception:

3, 0
8UC3
OpenCV Error: Assertion failed (L.channels() == 1 && I.channels() == 1) in connectedComponents_sub1, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 341
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:341: error: (-215) L.channels() == 1 && I.channels() == 1 in function connectedComponents_sub1

Now I know why I'm getting this error. According to the connectComponents documentation, it only supports image types CV_32S and CV_16U. I confirmed this when I changed the line

auto nLabels = cv::connectedComponents(bw, labelImage, 8);

to

auto nLabels = cv::connectedComponents(bw, labelImage, 8, CV_8S);

and got the following exception:

3, 0
8UC3
OpenCV Error: Unsupported format or combination of formats (the type of labels must be 16u or 32s) in connectedComponents, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 377
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:377: error: (-210) the type of labels must be 16u or 32s in function connectedComponents

The problem is I don't know how to fix this. Is there a work around for this? If you'd like to try the entire code you can download it from my github account here.

****** Original Question *******

Hi,

I am detecting multiple objects of different color from a video stream. I would like to count how many objects of each color appear in the stream. I am using OpenCV 2.4.8 on Ubuntu 14.04. Here is the code:

#!/usr/bin/env python
import cv2
import numpy as np
 [C:\fakepath\test.png](/upfiles/14515268783061356.png)
cap = cv2.VideoCapture(0)

while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])

    # define range of red color in HSV
    lower_red = np.array([160, 100, 100])
    upper_red = np.array([179, 255, 255])

    # Threshold the HSV image to get only blue colors
    blue_mask = cv2.inRange(hsv, lower_blue, upper_blue)

    # Threshold the HSV image to get only red colors
    red_mask = cv2.inRange(hsv, lower_red, upper_red)

    # add the masks
    mask = red_mask + blue_mask

    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame, frame, mask = mask)

    # cv2.imshow('frame',frame)
    # cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

Attached is an image from the video stream. In that image there are 4 red boxes and 4 blue boxes which I would like to count.

Any help is appreciated. Thanks.C:\fakepath\image.png

Count number of colored objects in image

****** EDIT-1 *******

Sorry for the delayed response. Being new to OpenCV I did some research and found out that a connected components function was introduced in OpenCV 3.0 and it is only available in C++ (AFAIK) as shown here. So, I decided to to write my code in C++. I have also updated the test image (I would like to make it work on this before I got to video stream). Here is my code:

#include <iostream>
#include <vector>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;

// function to print type of mat
string type2str(int type) {
  string r;

  uchar depth = type & CV_MAT_DEPTH_MASK;
  uchar chans = 1 + (type >> CV_CN_SHIFT);

  switch ( depth ) {
    case CV_8U:  r = "8U"; break;
    case CV_8S:  r = "8S"; break;
    case CV_16U: r = "16U"; break;
    case CV_16S: r = "16S"; break;
    case CV_32S: r = "32S"; break;
    case CV_32F: r = "32F"; break;
    case CV_64F: r = "64F"; break;
    default:     r = "User"; break;
  }

  r += "C";
  r += (chans+'0');

  return r;
}
std;   

cv::Mat connect_components(cv::Mat img, int threshval)
{
    cv::Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
    cv::Mat labelImage(img.size(), CV_8S);
    auto nLabels = cv::connectedComponents(bw, labelImage, 8);
    vector<cv::Vec3b> colors(nLabels);
    colors[0] = cv::Vec3b(0, 0, 0); //background
    for(auto label = 1; label < nLabels; ++label){
        colors[label] = cv::Vec3b(255, 255, 255);
    }
    cv::Mat dst(img.size(), CV_8UC3);
    for(auto r = 0; r < dst.rows; ++r){
        for(auto c = 0; c < dst.cols; ++c){
            auto label = labelImage.at<int>(r, c);
            cv::Vec3b &pixel = dst.at<cv::Vec3b>(r, c);
            pixel = colors[label];
        }
    }

    return dst;
}

int main(int argc, char **argv)
{
    cv::VideoCapture webcam(0);

    if (!webcam.isOpened()) {
        cerr << "Cannot open webcam" << endl;
        exit(-1);
    }

    // Define range for blue and red color in HSV
    const cv::Scalar blue_range[] = { {110, 50, 50}, {130, 255, 255} };
    const cv::Scalar red_range[] = { {0, 200, 50}, {10, 255, 150} };

    cout << CV_MAJOR_VERSION << ", " << CV_MINOR_VERSION << endl;

    cv::Mat original_frame, color_mask[2], final_mask;
    while (true) {
        try {
            webcam.read(original_frame); // grab each frame
            cout << type2str(original_frame.type()) << endl;
            cv::Mat frame_hsv;
            cv::cvtColor(original_frame, frame_hsv, CV_BGR2HSV); // convert BGR to HSV

            // threshold HSV image to get only defined range colors
            cv::inRange(frame_hsv, blue_range[0], blue_range[1], color_mask[0]); 
            cv::inRange(frame_hsv, red_range[0], red_range[1], color_mask[1]);

            // add the masks
            final_mask = color_mask[0] + color_mask[1];

            // Bitwise-AND full mask and original image
            cv::Mat colored_boxes;
            cv::bitwise_and(original_frame, original_frame, colored_boxes, final_mask);

            // Apply morphological closing
            cv::Mat morphed_boxes;
            cv::morphologyEx(colored_boxes, morphed_boxes, cv::MORPH_CLOSE, cv::Mat::ones(10, 10, CV_8UC1));

            // Connected componenets
            auto labeled_boxes = connect_components(colored_boxes, 62);

            // Display the image
            //cv::imshow("Webcam", original_frame);
            cv::imshow("Boxes", morphed_boxes);

            // quit progrem is user inputs ESC or q
            auto user_input = (cv::waitKey(5) & 0xFF);
            if ((user_input == 27) || (user_input == 113)) {
                break;
            }
        }
        catch (cv::Exception &e) {
            cout << "Exception caught" << endl;
            cout << e.what();
            break;
        }
    }

    return 0;
}

The connected_components function is adopted from here.

When I run this, I get the following exception:

3, 0
8UC3
OpenCV Error: Assertion failed (L.channels() == 1 && I.channels() == 1) in connectedComponents_sub1, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 341
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:341: error: (-215) L.channels() == 1 && I.channels() == 1 in function connectedComponents_sub1

Now I know why I'm getting this error. According to the connectComponents documentation, it only supports image types CV_32S and CV_16U. I confirmed this when I changed the line

auto nLabels = cv::connectedComponents(bw, labelImage, 8);

to

auto nLabels = cv::connectedComponents(bw, labelImage, 8, CV_8S);

and got the following exception:

3, 0
8UC3
OpenCV Error: Unsupported format or combination of formats (the type of labels must be 16u or 32s) in connectedComponents, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 377
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:377: error: (-210) the type of labels must be 16u or 32s in function connectedComponents

The problem is I don't know how to fix this. Is there a work around for this? If you'd like to try the entire code you can download it from my github account here.

****** Original Question *******

Hi,

I am detecting multiple objects of different color from a video stream. I would like to count how many objects of each color appear in the stream. I am using OpenCV 2.4.8 on Ubuntu 14.04. Here is the code:

#!/usr/bin/env python
import cv2
import numpy as np
[C:\fakepath\test.png](/upfiles/14515268783061356.png)
cap = cv2.VideoCapture(0)

while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])

    # define range of red color in HSV
    lower_red = np.array([160, 100, 100])
    upper_red = np.array([179, 255, 255])

    # Threshold the HSV image to get only blue colors
    blue_mask = cv2.inRange(hsv, lower_blue, upper_blue)

    # Threshold the HSV image to get only red colors
    red_mask = cv2.inRange(hsv, lower_red, upper_red)

    # add the masks
    mask = red_mask + blue_mask

    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame, frame, mask = mask)

    # cv2.imshow('frame',frame)
    # cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

Attached is an image from the video stream. In that image there are 4 red boxes and 4 blue boxes which I would like to count.

Any help is appreciated. Thanks.C:\fakepath\image.png

Count number of colored objects in image

****** EDIT-1 *******

Sorry for the delayed response. Being new to OpenCV I did some research and found out that a connected components function was introduced in OpenCV 3.0 and it is only available in C++ (AFAIK) as shown here. So, I decided to to write my code in C++. I have also updated the test image (I would like to make it work on this before I got to video stream). Here is my code:

#include <iostream>
#include <vector>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;   

cv::Mat connect_components(cv::Mat img, int threshval)
{
    cv::Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
    cv::Mat labelImage(img.size(), CV_8S);
    auto nLabels = cv::connectedComponents(bw, labelImage, 8);
    vector<cv::Vec3b> colors(nLabels);
    colors[0] = cv::Vec3b(0, 0, 0); //background
    for(auto label = 1; label < nLabels; ++label){
        colors[label] = cv::Vec3b(255, 255, 255);
    }
    cv::Mat dst(img.size(), CV_8UC3);
    for(auto r = 0; r < dst.rows; ++r){
        for(auto c = 0; c < dst.cols; ++c){
            auto label = labelImage.at<int>(r, c);
            cv::Vec3b &pixel = dst.at<cv::Vec3b>(r, c);
            pixel = colors[label];
        }
    }

    return dst;
}

int main(int argc, char **argv)
{
    cv::VideoCapture webcam(0);

    if (!webcam.isOpened()) {
        cerr << "Cannot open webcam" << endl;
        exit(-1);
    }

    // Define range for blue and red color in HSV
    const cv::Scalar blue_range[] = { {110, 50, 50}, {130, 255, 255} };
    const cv::Scalar red_range[] = { {0, 200, 50}, {10, 255, 150} };

    cout << CV_MAJOR_VERSION << ", " << CV_MINOR_VERSION << endl;

    cv::Mat original_frame, color_mask[2], final_mask;
    while (true) {
        try {
            webcam.read(original_frame); // grab each frame
            cv::Mat frame_hsv;
            cv::cvtColor(original_frame, frame_hsv, CV_BGR2HSV); // convert BGR to HSV

            // threshold HSV image to get only defined range colors
            cv::inRange(frame_hsv, blue_range[0], blue_range[1], color_mask[0]); 
            cv::inRange(frame_hsv, red_range[0], red_range[1], color_mask[1]);

            // add the masks
            final_mask = color_mask[0] + color_mask[1];

            // Bitwise-AND full mask and original image
            cv::Mat colored_boxes;
            cv::bitwise_and(original_frame, original_frame, colored_boxes, final_mask);

            // Apply morphological closing
            cv::Mat morphed_boxes;
            cv::morphologyEx(colored_boxes, morphed_boxes, cv::MORPH_CLOSE, cv::Mat::ones(10, 10, CV_8UC1));

            // Connected componenets
            auto labeled_boxes = connect_components(colored_boxes, 62);

            // Display the image
            //cv::imshow("Webcam", original_frame);
            cv::imshow("Boxes", morphed_boxes);

            // quit progrem is user inputs ESC or q
            auto user_input = (cv::waitKey(5) & 0xFF);
            if ((user_input == 27) || (user_input == 113)) {
                break;
            }
        }
        catch (cv::Exception &e) {
            cout << "Exception caught" << endl;
            cout << e.what();
            break;
        }
    }

    return 0;
}

The connected_components function is adopted from here.

. When I run this, I get the following exception:

3, 0
8UC3
OpenCV Error: Assertion failed (L.channels() == 1 && I.channels() == 1) in connectedComponents_sub1, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 341
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:341: error: (-215) L.channels() == 1 && I.channels() == 1 in function connectedComponents_sub1

Now I think I know why I'm getting this error. According to the connectComponents documentation, it only supports image types CV_32S and CV_16U. I confirmed this when I changed the line

auto nLabels = cv::connectedComponents(bw, labelImage, 8);

to

auto nLabels = cv::connectedComponents(bw, labelImage, 8, CV_8S);

and got the following exception:

3, 0
8UC3
OpenCV Error: Unsupported format or combination of formats (the type of labels must be 16u or 32s) in connectedComponents, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 377
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:377: error: (-210) the type of labels must be 16u or 32s in function connectedComponents

The problem is I don't know how to fix this. Is there a work around for this? If you'd like to try the entire code you can download it from my github account here.

****** Original Question *******

Hi,

I am detecting multiple objects of different color from a video stream. I would like to count how many objects of each color appear in the stream. I am using OpenCV 2.4.8 on Ubuntu 14.04. Here is the code:

#!/usr/bin/env python
import cv2
import numpy as np
[C:\fakepath\test.png](/upfiles/14515268783061356.png)
cap = cv2.VideoCapture(0)

while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])

    # define range of red color in HSV
    lower_red = np.array([160, 100, 100])
    upper_red = np.array([179, 255, 255])

    # Threshold the HSV image to get only blue colors
    blue_mask = cv2.inRange(hsv, lower_blue, upper_blue)

    # Threshold the HSV image to get only red colors
    red_mask = cv2.inRange(hsv, lower_red, upper_red)

    # add the masks
    mask = red_mask + blue_mask

    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame, frame, mask = mask)

    # cv2.imshow('frame',frame)
    # cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

Attached is an image from the video stream. In that image there are 4 red boxes and 4 blue boxes which I would like to count.

Any help is appreciated. Thanks.C:\fakepath\image.png

Count number of colored objects in image

****** EDIT-1EDIT-2 *******

Sorry for the delayed response. Being new to OpenCV I did some research and found out that a connected components function was introduced in OpenCV 3.0 and it is only available in C++ (AFAIK) as shown here. So, I decided to to write my code in C++. Based on the comment from Tetragramm, I have also updated the test image (I would like to make it work on this before I got to video stream). Here is my code:

#include <iostream>
#include <vector>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;   

cv::Mat connect_components(cv::Mat img, int threshval)
{
    cv::Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
    cv::Mat labelImage(img.size(), CV_8S);
    auto nLabels = cv::connectedComponents(bw, labelImage, 8);
    vector<cv::Vec3b> colors(nLabels);
    colors[0] = cv::Vec3b(0, 0, 0); //background
    for(auto label = 1; label < nLabels; ++label){
        colors[label] = cv::Vec3b(255, 255, 255);
    }
    cv::Mat dst(img.size(), CV_8UC3);
    for(auto r = 0; r < dst.rows; ++r){
        for(auto c = 0; c < dst.cols; ++c){
            auto label = labelImage.at<int>(r, c);
            cv::Vec3b &pixel = dst.at<cv::Vec3b>(r, c);
            pixel = colors[label];
        }
    }

    return dst;
}

int main(int argc, char **argv)
{
    cv::VideoCapture webcam(0);

    if (!webcam.isOpened()) {
        cerr << "Cannot open webcam" << endl;
        exit(-1);
    }

    // Define range for blue and red color in HSV
    const cv::Scalar blue_range[] = { {110, 50, 50}, {130, 255, 255} };
    const cv::Scalar red_range[] = { {0, 200, 50}, {10, 255, 150} };

    cout << CV_MAJOR_VERSION << ", " << CV_MINOR_VERSION << endl;

    cv::Mat original_frame, color_mask[2], final_mask;
    while (true) {
        try {
            webcam.read(original_frame); // grab each frame
            cv::Mat frame_hsv;
            cv::cvtColor(original_frame, frame_hsv, CV_BGR2HSV); // convert BGR to HSV

            // threshold HSV image to get only defined range colors
            cv::inRange(frame_hsv, blue_range[0], blue_range[1], color_mask[0]); 
            cv::inRange(frame_hsv, red_range[0], red_range[1], color_mask[1]);

            // add the masks
            final_mask = color_mask[0] + color_mask[1];

            // Bitwise-AND full mask and original image
            cv::Mat colored_boxes;
            cv::bitwise_and(original_frame, original_frame, colored_boxes, final_mask);

            // Apply morphological closing
            cv::Mat morphed_boxes;
            cv::morphologyEx(colored_boxes, morphed_boxes, cv::MORPH_CLOSE, cv::Mat::ones(10, 10, CV_8UC1));

            // Connected componenets
            auto labeled_boxes = connect_components(colored_boxes, 62);

            // Display the image
            //cv::imshow("Webcam", original_frame);
            cv::imshow("Boxes", morphed_boxes);

            // quit progrem is user inputs ESC or q
            auto user_input = (cv::waitKey(5) & 0xFF);
            if ((user_input == 27) || (user_input == 113)) {
                break;
            }
        }
        catch (cv::Exception &e) {
            cout << "Exception caught" << endl;
            cout << e.what();
            break;
        }
    }

    return 0;
}

The connected_components function is adopted from here. When I run this, I get the following simplified the connect_components function. However, I am still getting the same exception:

3, 0
8UC3
OpenCV Error: Assertion failed (L.channels() == 1 && I.channels() == 1) in connectedComponents_sub1, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 341
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:341: error: (-215) L.channels() == 1 && I.channels() == 1 in function connectedComponents_sub1

Maybe I shouldn't use the connectedComponenets function and go at it by the old way (which I'm not sure how to do, so an example would be great!)?

****** EDIT-1 *******

Sorry for the delayed response. Being new to OpenCV I did some research and found out that a connected components function was introduced in OpenCV 3.0 and it is only available in C++ (AFAIK) as shown here. So, I decided to to write my code in C++. I have also updated the test image (I would like to make it work on this before I got to video stream). Here is my code:

#include <iostream>
#include <vector>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;   


cv::Mat connect_components(cv::Mat img, int threshval)
{
    cv::Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
    cv::Mat labelImage(img.size(), CV_16U);
    auto nLabels = cv::connectedComponents(bw, labelImage, 8);
    bw = labelImage >= 1;
    cv::Mat bwArray[3] = {bw, bw, bw};
    cv::Mat dst(img.size(), CV_8UC3);
    cv::merge(bwArray, 3, dst);
    return dst;
}

int main(int argc, char **argv)
{
    cv::VideoCapture webcam(0);

    if (!webcam.isOpened()) {
        cerr << "Cannot open webcam" << endl;
        exit(-1);
    }

    // Define range for blue and red color in HSV
    const cv::Scalar blue_range[] = { {110, 50, 50}, {130, 255, 255} };
    const cv::Scalar red_range[] = { {0, 200, 50}, {10, 255, 150} };

    cout << CV_MAJOR_VERSION << ", " << CV_MINOR_VERSION << endl;

    cv::Mat original_frame, color_mask[2], final_mask;
    while (true) {
        try {
            webcam.read(original_frame); // grab each frame
            cv::Mat frame_hsv;
            cv::cvtColor(original_frame, frame_hsv, CV_BGR2HSV); // convert BGR to HSV

            // threshold HSV image to get only defined range colors
            cv::inRange(frame_hsv, blue_range[0], blue_range[1], color_mask[0]); 
            cv::inRange(frame_hsv, red_range[0], red_range[1], color_mask[1]);

            // add the masks
            final_mask = color_mask[0] + color_mask[1];

            // Bitwise-AND full mask and original image
            cv::Mat colored_boxes;
            cv::bitwise_and(original_frame, original_frame, colored_boxes, final_mask);

            // Apply morphological closing
            cv::Mat morphed_boxes;
            cv::morphologyEx(colored_boxes, morphed_boxes, cv::MORPH_CLOSE, cv::Mat::ones(10, 10, CV_8UC1));

            // Connected componenets
            auto labeled_boxes = connect_components(colored_boxes, 62);

            // Display the image
            //cv::imshow("Webcam", original_frame);
            cv::imshow("Boxes", morphed_boxes);

            // quit progrem is user inputs ESC or q
            auto user_input = (cv::waitKey(5) & 0xFF);
            if ((user_input == 27) || (user_input == 113)) {
                break;
            }
        }
        catch (cv::Exception &e) {
            cout << "Exception caught" << endl;
            cout << e.what();
            break;
        }
    }

    return 0;
}

The connected_components function is adopted from here. When I run this, I get the following exception:

3, 0
8UC3
OpenCV Error: Assertion failed (L.channels() == 1 && I.channels() == 1) in connectedComponents_sub1, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 341
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:341: error: (-215) L.channels() == 1 && I.channels() == 1 in function connectedComponents_sub1

I think I know why I'm getting this error. According to the connectComponents documentation, it only supports image types CV_32S and CV_16U. I confirmed this when I changed the line

auto nLabels = cv::connectedComponents(bw, labelImage, 8);

to

auto nLabels = cv::connectedComponents(bw, labelImage, 8, CV_8S);

and got the following exception:

3, 0
8UC3
OpenCV Error: Unsupported format or combination of formats (the type of labels must be 16u or 32s) in connectedComponents, file /source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp, line 377
Exception caught
/source/opencv-3.0.0/modules/imgproc/src/connectedcomponents.cpp:377: error: (-210) the type of labels must be 16u or 32s in function connectedComponents

The problem is I don't know how to fix this. Is there a work around for this? If you'd like to try the entire code you can download it from my github account here.

****** Original Question *******

Hi,

I am detecting multiple objects of different color from a video stream. I would like to count how many objects of each color appear in the stream. I am using OpenCV 2.4.8 on Ubuntu 14.04. Here is the code:

#!/usr/bin/env python
import cv2
import numpy as np
cap = cv2.VideoCapture(0)

while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])

    # define range of red color in HSV
    lower_red = np.array([160, 100, 100])
    upper_red = np.array([179, 255, 255])

    # Threshold the HSV image to get only blue colors
    blue_mask = cv2.inRange(hsv, lower_blue, upper_blue)

    # Threshold the HSV image to get only red colors
    red_mask = cv2.inRange(hsv, lower_red, upper_red)

    # add the masks
    mask = red_mask + blue_mask

    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame, frame, mask = mask)

    # cv2.imshow('frame',frame)
    # cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

Attached is an image from the video stream. In that image there are 4 red boxes and 4 blue boxes which I would like to count.

Any help is appreciated. Thanks.C:\fakepath\image.png