Opencv - FloodFill doesn't change mask image - android

I try to use floodFill algorithm on my android application. I click a point to select seed.Then I run floodfill algorithm. I want to show only selected area same as seed color. To do this, I display mask mat object. But it is black everytime, it doens't change. I used FLOODFILL_FIXED_RANGE and FLOODFILL_MASK_ONLY flags.
My code is here :
Imgproc.cvtColor(mRgba, temp, Imgproc.COLOR_RGBA2RGB);
Imgproc.cvtColor(temp, temp, Imgproc.COLOR_RGB2GRAY);
mMask = Mat.zeros(mMask.size(), CvType.CV_8UC1);
Imgproc.floodFill(temp, mMask, fpts.get(fpts.size()-1), new Scalar(255, 255, 255),new Rect(new Point(0,0), new Point(5,5)),new Scalar(30), new Scalar(30), Imgproc.FLOODFILL_FIXED_RANGE);
Core.circle(temp, fpts.get(fpts.size()-1), 7, new Scalar(255, 255, 255), RADIUS);
Mat temp3 = new Mat(temp.size(), mMask.type());
temp3 = mMask.submat(new Rect( 2, 2, mMask.width()-2, mMask.height()-2)) ;
Log.i(TAG, temp3.width() + "-" + temp3.height()+"**" + temp.width()+"-"+temp.height());
// / Show me what you got from template matching
Core.rectangle(temp, matchLoc, new Point(matchLoc.x + mTemp.cols(),
matchLoc.y + mTemp.rows()), new Scalar(0, 255, 0));
return temp3;
If I return temp, I can show changed input image.

You need to set the new value for the mask in the Imgproc.floodFill flags. To change the mask to white (255):
int flags = 4 + (255 << 8) + Imgproc.FLOODFILL_FIXED_RANGE;

Related

Detecting circles of a color gives "image must be 8-bit single-channel in HoughCircle" error in OpenCV

I am building an Android Application and I want to be able to detect black circles. I am using OpenCV3 for Android and I am able to filter out the black colours from my camera feed using the code below. Kindly note that I used the Color-blob-detection example given in the Android SDK and tweaked the code as such:
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
if (mIsColorSelected) {
Bitmap resultBitmap;
resultBitmap = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(),Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mRgba, resultBitmap);
//TODO - look for circles
Mat mat = new Mat(resultBitmap.getWidth(), resultBitmap.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(resultBitmap, mat);
final Bitmap bitmap;
//TODO - filter out the black only
Mat mHSV = mat;
Mat mHSVThreshed = mat;
Mat mRgba2 = mat;
Imgproc.cvtColor(mat, mHSV, Imgproc.COLOR_BGR2HSV, 0);
Core.inRange(mHSV, new Scalar(0, 0, 0), new Scalar(130, 130, 130), mHSVThreshed);
Imgproc.cvtColor(mHSVThreshed, mat, Imgproc.COLOR_GRAY2BGR, 0);
Imgproc.cvtColor(mat, mRgba2, Imgproc.COLOR_BGR2RGBA, 0);
Imgproc.GaussianBlur(mRgba2, mRgba2, new Size(9, 9), 2, 2);
//this is for displaying purposes only.
//At this point, the image would be black and white, where the white spots are the black detected blobs
// Bitmap bmp = Bitmap.createBitmap(mRgba2.cols(), mRgba2.rows(), Bitmap.Config.ARGB_8888);
//Utils.matToBitmap(mRgba2, bmp);
//bitmap = bmp; //resultBitmap;
//TODO - new circle detection code: this uses the colour filtered Mat
mat = mRgba2;
Imgproc.HoughCircles(mat, circles,
Imgproc.CV_HOUGH_GRADIENT, 1, minDist, 100,
20, 0, 0);
/* 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++) {
/* 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];
Point center = new Point(x, y);
int radius = (int) circleCoordinates[2];
/* circle's outline */
Imgproc.circle(mRgba2, center, radius, new Scalar(0,
200, 255), 4);
/* circle's center outline */
Imgproc.rectangle(mRgba2, new Point(x - 5, y - 5),
new Point(x + 5, y + 5),
new Scalar(0, 200, 255), -1);
}
Utils.matToBitmap(mRgba2, resultBitmap);
bitmap = resultBitmap;
runOnUiThread(new Runnable() {
#Override
public void run() {
mOpenCvCameraView.disableView();
mOpenCvCameraView.setVisibility(SurfaceView.GONE);
imageView.setVisibility(View.VISIBLE);
imageView.setImageBitmap(bitmap);
}
});
}
return mRgba;
}
What my code does is that it takes a snapshot of the camera feed as a Mat, and then using that Mat, I do some image processing on it and to black out everything except the black colour. The resulting Mat is the mRgba2 variable and I converted to Bitmap and displayed on an ImageView. I displayed this Bitmap to confirm that I am getting the result I want.
After I know that I'm able to filter out the colour I wanted, I then run a GaussianBlur on it then proceed to run HoughCircles. However, when I run the
Imgproc.HoughCircles(mat, circles,
Imgproc.CV_HOUGH_GRADIENT, 1, minDist, 100,
20, 0, 0);
line, I get an
The source image must be 8-bit, single-channel in function CvSeq* cvHoughCircles(CvArr*, void*, int, double, double, double, double, int, int)
Error.
I know that the code wherein I run HoughCircles on a given mat variable works, because I tested it before. Now, changing the mat variable I feed onto it does not, and I wonder what I did differently for the code to not work.
HoughCircles runs only on grayscale (CV8U) images.
Replacing
Imgproc.cvtColor(mat, mRgba2, Imgproc.COLOR_BGR2RGBA, 0);
with
Imgproc.cvtColor(mat, mRgba2, Imgproc.COLOR_BGR2GRAY, 0);
should remove the error.
Then the problem is to detect circles of a given color. This won't pose much of a problem in your case, because you are detecting black circles anyway. Instead of black circles, this will detect dark circles.
If you have dark colors other than black in some of the circles, you can filter them out separately by looking at the pixel values in a different color space.

OpenCv Core.add error

I've a problem with this metod of opencv library...
Imgproc.cvtColor(image , image , Imgproc.COLOR_RGBA2RGB);
Mat prob_fgd = new Mat(1, 1, CvType.CV_8U,
new Scalar(Imgproc.GC_PR_FGD));
try {
Imgproc.grabCut(image, firstMask, rect, bgModel, fgModel, 3, 0);
} catch (Exception w) {
System.out.println(w.getMessage());
}
Core.compare(firstMask, prob_fgd, firstMask, Core.CMP_EQ);
foreground = new Mat(image.size(), CvType.CV_8UC3, new Scalar(255, 255,
255));
image.copyTo(foreground, firstMask);
Imgproc.resize(background, background, image.size());
mask = new Mat(image.size(), CvType.CV_8UC1, new Scalar(100, 255,
100));
foreground = overlay_colored_roi(foreground, new Scalar(100, 255, 100));
Imgproc.cvtColor(foreground, mask, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(mask, mask, 254, 255, Imgproc.THRESH_BINARY_INV);
mask.copyTo(ref);
vals = new Mat(1, 1, CvType.CV_8UC3, new Scalar(0.0));
background.copyTo(dst);
background.setTo(vals, mask);
until here the code works.
here it stop.
log say that input element of core.add must have the same size but background.size()) foreground.size()) dst.size()) mask.size()) are equals.
Core.add(background, foreground, dst, mask);
They also must have the same number of channels.Since in the code background initialization is not shown I'm assuming that must be the problem.Secondly try normal addition function that is without the mask and check the output.If the problem still persists post the full code.Hope this helps.

how to detect eye pupil circularly in opencv

I am working on opencv in android and i want to change eye pupil color through Hue channel and i achieve this already but the problem is that the region i detected is in rectangle but i want this region circular as eye pupil is circular region. kindly help how i achieve this.
private Mat get_template(CascadeClassifier clasificator, Rect area,int size){
Mat template = new Mat();
Mat mROI = mGray.submat(area);
MatOfRect eyes = new MatOfRect();
Point iris = new Point();
Rect eye_template = new Rect();
clasificator.detectMultiScale(mROI, eyes, 1.15, 2,Objdetect.CASCADE_FIND_BIGGEST_OBJECT|Objdetect.CASCADE_SCALE_IMAGE, new Size(30,30),new Size());
Rect[] eyesArray = eyes.toArray();
for (int i = 0; i < eyesArray.length; i++){
Rect e = eyesArray[i];
e.x = area.x + e.x;
e.y = area.y + e.y;
Rect eye_only_rectangle = new Rect((int)e.tl().x,(int)( e.tl().y + e.height*0.4),(int)e.width,(int)(e.height*0.6));
mROI = mGray.submat(eye_only_rectangle);
Mat vyrez = mRgba.submat(eye_only_rectangle);
Core.MinMaxLocResult mmG = Core.minMaxLoc(mROI);
Core.circle(vyrez, mmG.minLoc,2, new Scalar(255, 255, 255, 255),2);
iris.x = mmG.minLoc.x + eye_only_rectangle.x;
iris.y = mmG.minLoc.y + eye_only_rectangle.y;
eye_template = new Rect((int)iris.x-size/2,(int)iris.y-size/2 ,size,size);
Core.rectangle(mRgba,eye_template.tl(),eye_template.br(),new Scalar(255, 0, 0, 255), 2);
template = (mGray.submat(eye_template)).clone();
return template;
}
return template;
}
Some potential solutions:
the simplest, although it might not be very robust is to calculate the inscribed circle (the circle bound by the rectangle) and change it's color - if your pupil detection is very accurate this solution may work fine.
a more robust solution would be to detect the area of the pupil based on color or gradient (edge detection)

OpenCV Template Matching Drawing Rectangle Around Match

I want to use template matching, i am utilizing a code that i found that does what i want where it keeps it in bitmap and get a return of bitmap, the problem is im not entirely sure how i can get to drawing in the rectangles. I am using only java, no native while creating an app for android. With the use of openCV which i am new at. I will get multiple matches so i would like to get drawn rectangles around those point and also be able to obtain a value for the locations of these matches.
mFind=new Mat(256, 192, CvType.CV_8UC4);
Input = new Mat(256, 192, CvType.CV_8UC4);
Mat mResult8u = new Mat(256, 192, CvType.CV_8UC4);
mResult = new Mat(217, 153, CvType.CV_8UC4);
Utils.bitmapToMat(bmp2, mFind);
Utils.bitmapToMat(bmp1, Input);
Imgproc.matchTemplate(mFind, Input, mResult, Imgproc.TM_SQDIFF) ;
bmp3= Bitmap.createBitmap(mResult.cols(), mResult.rows(),Bitmap.Config.ARGB_8888);
Core.normalize(mResult, mResult8u, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);
Utils.matToBitmap(mResult8u, bmp3);
iv2.setImageBitmap(bmp3);
Find the match in your mResult, paint the rect on the Input using Core.rectangle and write this into file.
// / Localizing the best match with minMaxLoc
MinMaxLocResult mmr = Core.minMaxLoc(mResult);
Point matchLoc;
if (match_method == Imgproc.TM_SQDIFF || match_method == Imgproc.TM_SQDIFF_NORMED) {
matchLoc = mmr.minLoc;
} else {
matchLoc = mmr.maxLoc;
}
// / Show me what you got
Core.rectangle(Input, matchLoc, new Point(matchLoc.x + templ.cols(),
matchLoc.y + templ.rows()), new Scalar(0, 255, 0));
// Save the visualized detection.
System.out.println("Writing "+ outFile);
Highgui.imwrite(outFile, img);

Android OpenCV eye-tracking by color detection

I have a code which detect face, both eyes and then the pupil of each eyes. Now I want to detect the corners of each eyes by using white color detection. As I am new to opencv could you please guide me that how should I do this and provide me with an android sample code? This is a part of the code which I have:
for (int i = 0; i < facesArray.length; i++){
Rect r = facesArray[i];
Core.rectangle(mGray, r.tl(), r.br(), new Scalar(0, 255, 0, 255), 3);
Core.rectangle(mRgba, r.tl(), r.br(), new Scalar(0, 255, 0, 255), 3);
eyearea = new Rect(r.x +r.width/8,(int)(r.y + (r.height/4.5)),r.width - 2*r.width/8,(int)( r.height/3.0));
Core.rectangle(mRgba,eyearea.tl(),eyearea.br() , new Scalar(255,0, 0, 255), 2);
Rect eyearea_right = new Rect(r.x +r.width/16,(int)(r.y + (r.height/4.5)),(r.width - 2*r.width/16)/2,(int)( r.height/3.0));
Rect eyearea_left = new Rect(r.x +r.width/16 +(r.width - 2*r.width/16)/2,(int)(r.y + (r.height/4.5)),(r.width - 2*r.width/16)/2,(int)( r.height/3.0));
Core.rectangle(mGray,eyearea_left.tl(),eyearea_left.br() , new Scalar(255,0, 0, 255), 2);
Core.rectangle(mRgba,eyearea_right.tl(),eyearea_right.br() , new Scalar(255, 0, 0, 255), 2);
if(learn_frames<5){
//This part detect the pupil of the eyes
teplateR = get_template(mCascadeER,eyearea_right,20);
teplateL = get_template(mCascadeEL,eyearea_left,20);
learn_frames++;
}else{
match_value = match_eye(eyearea_right,teplateR,FdActivity.method);
match_value = match_eye(eyearea_left,teplateL,FdActivity.method);
;
}
Imgproc.resize(mRgba.submat(eyearea_left), mZoomWindow2, mZoomWindow2.size());
Imgproc.resize(mRgba.submat(eyearea_right), mZoomWindow, mZoomWindow.size());
}
You need something like Flandmark to detect corners.
See: http://cmp.felk.cvut.cz/~uricamic/flandmark/

Categories

Resources