Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ OpenCV
I'm going to identify currency notes base on color.I used histogram for this.I could identify only R,G,B values.How can i detect yellow and brown color.This is what i'm done so far.are there any other methods to detect color with out going for histogram.
 
#include "stdafx.h"
#include <cv.h>
#include <iostream>
#include <highgui.h>
#include <cxcore.h>
 
int _tmain(int argc, _TCHAR* argv[])
{
IplImage* img  = cvLoadImage("500.jpg");
 

 if( !img )
   return -1;
 
 IplImage* channel = cvCreateImage( cvGetSize(img), 8, 1 );
 IplImage *hist_img = cvCreateImage(cvSize(300,240), 8, 3);
  IplImage *hist_imgfinal = cvCreateImage(cvSize(300,240), 8, 3);
 IplImage *hist_red1 = cvCreateImage(cvSize(300,240), 8, 3);
IplImage *hist_blue1 = cvCreateImage(cvSize(300,240), 8, 3);
IplImage *hist_green1 = cvCreateImage(cvSize(300,240), 8, 3);
 IplImage *mer1 = cvCreateImage(cvSize(300,240), 8, 3);
IplImage *mer2 = cvCreateImage(cvSize(300,240), 8, 3);
IplImage *mer3 = cvCreateImage(cvSize(300,240), 8, 3);
cvSet( hist_img, cvScalarAll(255), 0 );
 
 CvHistogram *hist_red;
 CvHistogram *hist_green;
 CvHistogram *hist_blue;
 
    int hist_size = 256;
    float range[]={0,256};
    float* ranges[] = { range };
 
    float max_value = 0.0;
     float max_valueb = 0.0;
     float max_valuer = 0.0;
     float max_valueg = 0.0;
    float max = 0.0;
        float maxb = 0.0;
        float maxg = 0.0;
    float w_scale = 0.0;
 

 hist_red = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
 hist_green = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
 hist_blue = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
 
 /* Set image to obtain RED as Channel of Interest (COI) */
  cvSetImageCOI(img,3);
  cvCopy(img,channel);
  cvResetImageROI(img);
 
 /* Calculate histogram of the Image and store it in the array */
  cvCalcHist( &channel, hist_red, 0, NULL );
 
 /* Calculate and Plot the histograms Green and Blue channels as well */
 /* Green channel */
  cvSetImageCOI(img,2);
  cvCopy(img,channel);
  cvResetImageROI(img);
 
  cvCalcHist( &channel, hist_green, 0, NULL );
 
 /* Blue channel */
  cvSetImageCOI(img,1);
  cvCopy(img,channel);
  cvResetImageROI(img);
 
  cvCalcHist( &channel, hist_blue, 0, NULL );
 

/* Find the minimum and maximum values of the histograms */
 cvGetMinMaxHistValue( hist_red, 0, &max_valuer, 0, 0 );
 cvGetMinMaxHistValue( hist_green, 0, &maxg, 0, 0 );
 
 max_value = (maxg > max_valuer) ? maxg : max_valuer;
 
 cvGetMinMaxHistValue( hist_blue, 0, &maxb, 0, 0 );
 
 max_valueb = (maxb > max_value) ? maxb : max_value;
  // The variable max_value has the maximum of the three histograms
//hist = cvCreateHist(1, hsize, CV_HIST_ARRAY, ranges,1);
//cvCalcHist(planes, hist, 0, NULL);
//cvGetMinMaxHistValue(hist, &min_value, &max_value);
printf("Maximum Histogram Value: %f\n",max_valueb );
printf("Maximum Histogram Value blue");
 

 
 /* Using the maximum value, Scale/Squeeze the histogram (to fit the image) */
 cvScale( hist_red->bins, hist_red->bins, ((float)hist_img->height)/max_value, 0 );
 cvScale( hist_green->bins, hist_green->bins, ((float)hist_img->height)/max_value, 0 );
 cvScale( hist_blue->bins, hist_blue->bins, ((float)hist_img->height)/max_value, 0 );
 

  //A scale to estimate the number of pixels

// printf("Scale: %4.2f pixels per 100 units\n", max_value*100/((float)hist_img->height));

    /* Scale/Squeeze the histogram range to image width */
w_scale = ((float)hist_img->width)/hist_size;
 
/* Plot the Histograms */
    for( int i = 0; i < hist_size; i++ )
    {
 
      cvRectangle( hist_img, cvPoint((int)i*w_scale , hist_img->height),
        cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_red->bins,i))),
        CV_RGB(255,0,0), -1, 8, 0 );
      cvRectangle( hist_img, cvPoint((int)i*w_scale , hist_img->height),
       cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_green->bins,i))),
       CV_RGB(0,255,0), -1, 8, 0 );
      cvRectangle( hist_img, cvPoint((int)i*w_scale , hist_img->height),
       cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_blue->bins,i))),
       CV_RGB(0,0,255), -1, 8, 0 );
    }
 
 for( int i = 0; i < hist_size; i++ )
    {
        cvRectangle( hist_red1, cvPoint((int)i*w_scale , hist_img->height),
        cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_red->bins,i))),
        CV_RGB(255,0,0), -1, 8, 0 );
     }
     for( int i = 0; i < hist_size; i++ )
    {
        cvRectangle( hist_green1, cvPoint((int)i*w_scale , hist_img->height),
       cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_green->bins,i))),
       CV_RGB(0,255,0), -1, 8, 0 );
     }
      for( int i = 0; i < hist_size; i++ )
    {
        cvRectangle( hist_blue1, cvPoint((int)i*w_scale , hist_img->height),
       cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_blue->bins,i))),
       CV_RGB(0,0,255), -1, 8, 0 );
     }
 

cvAdd(hist_red1,hist_green1,mer1,0);
cvAdd(hist_red1,hist_blue1,mer2,0);
cvAdd(hist_green1,hist_blue1,mer3,0);
 

 

    return 0;
}
Posted 18-May-12 21:03pm
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Color processing or color vision may sound simple but i suggest you think again. With some inspiration from human visual system. http://en.wikipedia.org/wiki/Color_vision[^]
 
It starts out as an opponent process http://en.wikipedia.org/wiki/Opponent_process[^]
 
In which color channels R,G,B are converted to Red vs Green ( R - G) ,blue vs yellow ( B - (R+G)/2) and achromatic channel (R/3 + G/3 + B/3). It seems to be imperative to start out that way. You can then filter these resulting channels to remove noise with a box filter using integral images(for speed) or a gaussian filter. Then during the learning phase your app can obtain a 3 - dimensional vector at any given position (one component from each channel) and normalize it and label it and store it as a prototype in an indexing structure such as the kd-tree.http://en.wikipedia.org/wiki/K-d_tree[^]
At run time your app can then label each pixel with it's associated color based on the closest prototype in the indexing structure.
 
This is a very simplified version of color processing, it goes far than this. Just wanted to share my thoughts on this matter and help you to see other possibilities. I prefer the opponent channels to R,G,B channels in the sense that opponent processing is inspired by human visual system and it probably out performs methods that use direct R,G,B value because the opponent process seem to enhance contrast between channels.
 
Glad to help Smile | :)
  Permalink  
Comments
Nelek at 26-May-12 17:29pm
   
Nice answer
BupeChombaDerrick at 26-May-12 17:46pm
   
Thanks :)
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Another solution without histogram is: you need to create a filter matrix (or IplImage) filled with the color you want to detect.
 
Assume that your input is IplImage* img;
 
All you need is to do the logical 'AND' operator on the input and the filter, the result will turn out non-zero at the detected region.
 
IplImage* brownFilter = cvCreateImage( cvGetSize(img), 8, 1 ); // Same size as the input
IplImage* detectionResult = cvCreateImage( cvGetSize(img), 8, 1 );
 
cvZero( detectionResult );
cvSet( brownFilter, CV_RGB(90,40,10) ); // Your color you wanna detect

cvAnd( brownFilter, img, detectionResult, NULL );
 
// Now the result is stored in the detection result
cvNamedWindow("result");
cvShowImage("result", detectionResult );
cvWaitKey( 0 ); // Halt the screen

 
For more advanced, if you'd like to detect the similar color (not exactly the same RGB), you need to calculate the distance between
 
the color of each pixel to the filter color instead. If the distance does not exceed that certain threshold value, it is treated as a detected region.
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Advertise | Privacy | Mobile
Web04 | 2.8.1411022.1 | Last Updated 26 May 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100