Android OpenCV圆圈HSV颜色检测

时间:2016-04-16 20:14:26

标签: java android opencv xamarin opencv4android

我是OpenCV的新手,我正在尝试使用Android应用找到我的圈子和颜色。我正在使用Xamarin.Net.Android/C#和OpenCV SDK(Java Binded Library)。我可以找到圆圈,但我找不到我的圆圈有六种颜色(橙色,黄色,绿色,紫色,红色,蓝色)的颜色。我找到了一个示例c代码,但我无法集成到我的项目中。这是我的android opencv onCameraFrame方法。

public Mat OnCameraFrame(CameraBridgeViewBase.ICvCameraViewFrame inputFrame)
    {
        Mat rgba = inputFrame.Rgba();
        Size sizeRgba = rgba.Size();
        Mat rgbaInnerWindow;
        int rows = (int)sizeRgba.Height;
        int cols = (int)sizeRgba.Width;
        int left = cols / 8;
        int top = rows / 8;
        int width = cols * 3 / 4;
        int height = rows * 3 / 4;
        Mat mat = rgba;
        Mat grayMat = new Mat(height, width, CvType.Cv8uc4);

        /* convert to grayscale */
        int colorChannels = (mat.Channels() == 3) ? Imgproc.ColorBgr2gray
          : ((mat.Channels() == 4) ? Imgproc.ColorBgra2gray : 1);
        Imgproc.CvtColor(mat, grayMat, colorChannels, 4);
        /* reduce the noise so we avoid false circle detection */
        Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2);

        // accumulator value
        double dp = 1.3d;
        // minimum distance between the center coordinates of detected circles in pixels
        double minDist = 100;

        // min and max radii (set these values as you desire)
        int minRadius = 0, maxRadius = 50;

        // param1 = gradient value used to handle edge detection
        // param2 = Accumulator threshold value for the
        // cv2.CV_HOUGH_GRADIENT method.
        // The smaller the threshold is, the more circles will be
        // detected (including false circles).
        // The larger the threshold is, the more circles will
        // potentially be returned.
        double param1 = 70, param2 = 72;

        /* create a Mat object to store the circles detected */
        Mat circles = new Mat(height,
                width, CvType.Cv8uc1);

        /* find the circle in the image */
        Imgproc.HoughCircles(grayMat, circles,
    Imgproc.CvHoughGradıent, dp, minDist, param1,
    param2, minRadius, maxRadius);

        /* get the number of circles detected */
        int numberOfCircles = (circles.Rows() == 0) ? 0 : circles.Cols();

        /* draw the circles found on the image */
        for (int i = 0; i < numberOfCircles; i++)
        {
            int matches = 0;
            var p = circles.Get(0, i);


            /* get the circle details, circleCoordinates[0, 1, 2] = (x,y,r)
             * (x,y) are the coordinates of the circle's center
             */
            double[] circleCoordinates = circles.Get(0, i);


            int x = (int)circleCoordinates[0], y = (int)circleCoordinates[1];
            double r = p[2];

            Point center = new Point(x, y);

            int radius = (int)circleCoordinates[2];

            /* circle's outline */
            Imgproc.Circle(mat, center, radius, new Scalar(0,
                    255, 0), 4);
            // I need the color here.
            Imgproc.PutText(mat, "Founded Circle Color is : xxx", center, Core.Core.FontItalıc, 1.0, new Scalar(0, 0, 0));
            /* circle's center outline */
            Imgproc.Rectangle(mat, new Point(x - 5, y - 5),
                    new Point(x + 5, y + 5),
                    new Scalar(0, 128, 255), -1);
        }


        return mat;
    }

工作的C代码在这里,但我无法为opencv 3.0实现它java / c#xamarin

#include <stdio.h>
#include <math.h>
#include <deque>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "opencv/cxcore.h"

using namespace std;

CvSeq* getCirclesInImage(IplImage*, CvMemStorage*, IplImage*);
float eucdist(CvPoint, CvPoint);
void drawCircleAndLabel(IplImage*, float*, const char*);
bool circlesBeHomies(float*, float*);

const int MIN_IDENT = 50;
const int MAX_RAD_DIFF = 10;
const int HISTORY_SIZE = 5;
const int X_THRESH = 15;
const int Y_THRESH = 15;
const int R_THRESH = 20;
const int MATCHES_THRESH = 3;
const int HUE_BINS = 32;

int main(int argc, char *argv[]) {
  CvCapture *capture = 0; //The camera
  IplImage* frame = 0; //The images you bring out of the camera

  //Open the camera
  capture = cvCaptureFromCAM( 0 );
  if (!capture ) {
    printf("Could not connect to camera\n" );
    return 1;
  }

  frame = cvQueryFrame( capture );
  //Create two output windows
  cvNamedWindow( "raw_video", CV_WINDOW_AUTOSIZE );
  cvNamedWindow( "processed_video", CV_WINDOW_AUTOSIZE );

  //Used as storage element for Hough circles
  CvMemStorage* storage = cvCreateMemStorage(0);

  // Grayscale image
  IplImage* grayscaleImg = cvCreateImage(cvSize(640, 480), 8/*depth*/, 1/*channels*/);

  CvPoint track1 = {-1, -1};
  CvPoint track2 = {-1, -1};
  float rad1 = -1;
  float rad2 = -1;
  deque<CvSeq*> samples;
  int key = 0;
  while(key != 27 /*escape key to quit*/ ) {
    //Query for the next frame
  frame = cvQueryFrame( capture );
  if( !frame ) break;

  deque<CvSeq*> stableCircles;
    //show the raw image in one of the windows
  cvShowImage( "raw_video", frame );
  CvSeq* circles = getCirclesInImage(frame, storage, grayscaleImg);

    //Iterate through the list of circles found by cvHoughCircles()
  for(int i = 0; i < circles->total; i++ ) {
    int matches = 0;
    float* p = (float*)cvGetSeqElem( circles, i );
    float x = p[0];
    float y = p[1];
    float r = p[2];
    if (x-r < 0 || y-r < 0 || x+r >= frame->width || y+r >= frame->height) {
        continue;
    }
    for (int j = 0; j < samples.size(); j++) {
        CvSeq* oldSample = samples[j];
        for (int k = 0; k < oldSample->total; k++) {
            float* p2 = (float*)cvGetSeqElem( oldSample, k );
            if (circlesBeHomies(p, p2)) {
                matches++;
                break;
            }
        }
    }
    if (matches > MATCHES_THRESH) {
        cvSetImageROI(frame, cvRect(x-r, y-r, 2*r, 2*r));
        IplImage* copy = cvCreateImage(cvSize(2*r, 2*r), frame->depth, 3);
        cvCvtColor(frame, copy, CV_BGR2HSV);
        IplImage* hue = cvCreateImage(cvGetSize(copy), copy->depth, 1);
        cvCvtPixToPlane(copy, hue, 0, 0, 0);
        int hsize[] = {HUE_BINS};
        float hrange[] = {0,180};
        float* range[] = {hrange};
        IplImage* hueArray[] = {hue};
        int channel[] = {0};
        CvHistogram* hist = cvCreateHist(1, hsize, CV_HIST_ARRAY, range, 1);
        cvCalcHist(hueArray, hist, 0, 0);
        cvNormalizeHist(hist, 1.0);
        int highestBinSeen = -1;
        float maxVal = -1;
        for (int b=0; b<HUE_BINS; b++) {
            float binVal = cvQueryHistValue_1D(hist, b);
            if (binVal > maxVal) {
                maxVal = binVal;
                highestBinSeen = b;
            }
        }
        cvResetImageROI(frame);
        const char *color;
        switch(highestBinSeen) {
            case 2: case 3: case 4:
            color = "orange";
            break;
            case 5: case 6: case 7: case 8:
            color = "yellow";
            break;
            case 9: case 10: case 11: case 12:
            case 13: case 14: case 15: case 16:
            color = "green";
            break;
            case 17: case 18: case 19: case 20:
            case 21: case 22: case 23:
            color = "blue";
            break;
            case 24: case 25: case 26: case 27:
            case 28:
            color = "purple";
            break;
            default:
            color = "red";
        }
        char label[64];
        sprintf(label, "color: %s", color);
        drawCircleAndLabel(frame, p, label);
    }
  }
  samples.push_back(circles);
  if (samples.size() > HISTORY_SIZE) {
    samples.pop_front();
  }
  cvShowImage( "processed_video", frame);

    //Get the last key that's been pressed for input
  key = cvWaitKey( 1 );
}
}

CvSeq* getCirclesInImage(IplImage* frame, CvMemStorage* storage, IplImage* grayscaleImg) {
  // houghification
  // Convert to a single-channel, grayspace image
    cvCvtColor(frame, grayscaleImg, CV_BGR2GRAY);

  // Gaussian filter for less noise
    cvSmooth(grayscaleImg, grayscaleImg, CV_GAUSSIAN, 7, 9 );

  //Detect the circles in the image
    CvSeq* circles = cvHoughCircles(grayscaleImg,
        storage,
        CV_HOUGH_GRADIENT,
        2,
        grayscaleImg->height/4,
        200,
        100 );
    return circles;
}

float eucdist(CvPoint c1, CvPoint c2) {
    float d = sqrt(pow((float)c1.x - c2.x, 2) + pow((float)c1.y - c2.y, 2));
    return d;
}

void drawCircleAndLabel(IplImage* frame, float* p, const char* label) {
  //Draw the circle on the original image
  //There's lots of drawing commands you can use!
    CvFont font;
    cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0.0, 1, 8);
    cvCircle( frame, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );
    cvPutText( frame, label, cvPoint(cvRound(p[0]),cvRound(p[1])), &font, CV_RGB(255,0,0) );
}

bool circlesBeHomies(float* c1, float* c2) {
    return (abs(c1[0]-c2[0]) < X_THRESH) && (abs(c1[1]-c2[1]) < Y_THRESH) &&
    (abs(c1[2]-c2[2]) < R_THRESH);
}

非常感谢。

1 个答案:

答案 0 :(得分:1)

我没有在java中使用opencv,但我使用c ++开发了一个带有下面显示代码的循环跟踪,这可能会帮助你解决问题。

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

using namespace cv;
using namespace std;

int main()
{

VideoCapture cap(0);

if(!cap.isOpened()) {

    cout << "The Camera Cannot be Loaded !!!" << endl;
    exit(-1);
}

while(true) {

    Mat bgrFrame, hsvFrame, detectedRedCircle;
    bool state = cap.read(bgrFrame);
    if(!state) {

        cout << "The frame cannot be grab" << endl;
        return -1;
    }

    //cvtColor(bgrFrame, detectedRedCircle, CV_BGR2GRAY);
    cvtColor(bgrFrame, hsvFrame, CV_BGR2HSV);
    //inRange(hsvFrame, Scalar(90, 50, 50), Scalar(130, 255, 255), detectedRedCircle);
    //inRange(hsvFrame, Scalar(100, 80, 80), Scalar(130, 255, 255), detectedRedCircle);
    inRange(hsvFrame, Scalar(110, 50, 50), Scalar(150, 255, 255), detectedRedCircle);
    GaussianBlur(detectedRedCircle, detectedRedCircle, Size(9, 9), 3, 3);
    vector<Vec3f> circles;
    //Canny(detectedRedCircle, detectedRedCircle, 9, 130, 3, false);
    Mat element = getStructuringElement(MORPH_ELLIPSE, Size(3, 3), Point(-1, -1));
    morphologyEx(detectedRedCircle, detectedRedCircle, 2, element);
    HoughCircles(detectedRedCircle, circles, CV_HOUGH_GRADIENT, 2, 5000 , 90, 70, 0, 0);
   // Mat element = getStructuringElement(1, Size(9, 9), Point(-1, -1));
   // morphologyEx(detectedRedCircle, detectedRedCircle, 3, element);

    for(int i = 0; i < circles.size(); i++) {

        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);
        if(radius > 40) continue;
        circle(bgrFrame, center, radius, Scalar(0, 255, 0), 3, 8, 0);
        //cout<<"Center : " << center << endl;
    }

    imshow("Orijinal Image", bgrFrame);
    imshow("Gray Image", detectedRedCircle);
    if(waitKey(30) == 27) break;
    }



    return 0;
}