我是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);
}
非常感谢。
答案 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;
}