Ask Your Question

Background color similar to object color - How isolate it?

asked 2014-01-08 18:53:29 -0600

Tomas gravatar image

updated 2020-10-28 03:02:35 -0600

I would isolate an object(in my case, a tuna) from the background. The problem is that they are very similar by color. Here is an example of image:

image description

For isolate, i mean, create a countour or change the color of the tuna, or something that isolate my object, because after i would make an object detection based on shape.

There are any elaboration, distorsion or technique that can i apply to my image to do that? Is it possible?

If not, what object detection tecnique should i use? P.S: think i cannot use background subtraction because my camera moves a little..

I'm very new of this world so i would be glad if someone can hel me :)

Thank you!!

edit retag flag offensive close merge delete


Preprocessing of underwater images is explained in this paper -

Spark gravatar imageSpark ( 2015-03-24 00:00:06 -0600 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2015-11-20 06:18:59 -0600

pklab gravatar image

updated 2019-04-07 08:29:05 -0600

This question is a bit old but user updated after year and recently I have had a similar problem. This case can be solved using brightness with few preprocessing threshold and contours. Here I would like to show that not always Hue is the way.

This is brightness after blur + equalization and its histogram: image description image description

This is the final result after threshold and contours to select the tuna

image description

And this is the code. There is a semi-automatic threshold but we have good bins separation in histogram. Play around params with trackbars.

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

using namespace std;
using namespace cv;

int useEqualize = 0;
int th1, blursSize;
const std::string winName = "Tuna fish";
cv::Mat src, dst;
cv::Mat brightness;

void onTunaFishTrackbar(int, void*)
    cv::Mat hist, histImg, tmp;

    if (blursSize >= 3)
        blursSize += (1 - blursSize % 2);
        cv::GaussianBlur(tmp, tmp, cv::Size(blursSize, blursSize), 0);
    if (useEqualize)
        cv::equalizeHist(tmp, tmp);

    cv::imshow("Brightness Preprocess", tmp);

    // threshold to select dark tuna
    cv::threshold(tmp, tmp, th1, 255, cv::THRESH_BINARY_INV);
    cv::imshow(winName, tmp);

    // find external contours ignores holes in the fish
    vector<vector<cv::Point> > contours;
    vector<cv::Vec4i> hierarchy;
    cv::findContours(tmp, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    // draw all contours and select the largest
    double maxDim = 0;
    int largest = -1;
    for (int i = 0; i < contours.size(); i++)
        // draw all contours in red
        cv::drawContours(dst, contours, largest, cv::Scalar(0, 0, 255), 1);
        int dim = contours[i].size(); //area is more accurate but more expensive
        //double dim = contourArea(contours[i]);
        //double dim = cvRound(arcLength(contours[i], true));
        if (dim > maxDim)
            maxDim = dim;
            largest = i;

    //The tuna as binary mask
    cv::Mat fishMask = cv::Mat::zeros(src.size(), CV_8UC1);
    //The tuna as contour
    vector<cv::Point> theFish;
    if (largest >= 0)
        theFish = contours[largest];
        // draw selected contour in bold green
        cv::polylines(dst, theFish, true, cv::Scalar(0, 255, 0), 2);
        // draw the fish into its mask
        cv::drawContours(fishMask, contours, largest, 255, -1);
    cv::imshow("Result Fish Mask", fishMask);
    cv::imshow("Result Contour", dst);

int main(int argc, char* argv[])
    src = cv::imread(argv[1]);
    if (src.empty())
        cout << endl
            << "ERROR! Unable to read the image" << endl
            << "Press a key to terminate";
        return 1;


    imshow(winName, src);
    imshow("Src", src);

    cvtColor(src, dst, COLOR_BGR2HSV);
    vector<cv::Mat > hsv_planes;
    split(dst, hsv_planes);
    //hue = hsv_planes[0];
    //saturation = hsv_planes[1];
    brightness = hsv_planes[2];

    // default settings for params
    useEqualize = 1;
    blursSize = 21;
    th1 = 33.0 * 255 / 100; //tuna is dark than select dark zone below 33% of full range
    cv::createTrackbar("Equalize", winName, &useEqualize, 1, onTunaFishTrackbar, 0);
    cv::createTrackbar("Blur Sigma", winName, &blursSize, 100, onTunaFishTrackbar, 0);
    cv::createTrackbar("Threshold", winName, &th1, 255, onTunaFishTrackbar, 0);

    onTunaFishTrackbar(0, 0);

    return 0;
edit flag offensive delete link more



Nice solution! Thumbs up!

StevenPuttemans gravatar imageStevenPuttemans ( 2015-11-23 08:46:26 -0600 )edit

Question Tools



Asked: 2014-01-08 18:53:29 -0600

Seen: 7,830 times

Last updated: Apr 07 '19