OpenCv Core.add error - android

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.

Related

Output image after Grabcut algorithm appears all black nothing init [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I had followed this tutorial to apply grab cut algorithm in opencv4android but my output image is not same as described in this tutorial. In fact the image I get is only black.
The output I get is this image Output image. I use same image used toturial
as input but my output was black.
Here is the code for grabcut in android opencv that solves your problem.
public void grabcutAlgo(Bitmap bit){
Bitmap b = bit.copy(Bitmap.Config.ARGB_8888, true);
Point tl=new Point();
Point br=new Point();
//GrabCut part
Mat img = new Mat();
Utils.bitmapToMat(b, img);
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2RGB);
int r = img.rows();
int c = img.cols();
Point p1 = new Point(c / 100, r / 100);
Point p2 = new Point(c - c / 100, r - r / 100);
Rect rect = new Rect(p1, p2);
//Rect rect = new Rect(tl, br);
Mat background = new Mat(img.size(), CvType.CV_8UC3,
new Scalar(255, 255, 255));
Mat firstMask = new Mat();
Mat bgModel = new Mat();
Mat fgModel = new Mat();
Mat mask;
Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
Mat dst = new Mat();
Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel, 5, Imgproc.GC_INIT_WITH_RECT);
Core.compare(firstMask, source, firstMask, Core.CMP_EQ);
Mat foreground = new Mat(img.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
img.copyTo(foreground, firstMask);
Scalar color = new Scalar(255, 0, 0, 255);
Imgproc.rectangle(img, tl, br, color);
Mat tmp = new Mat();
Imgproc.resize(background, tmp, img.size());
background = tmp;
mask = new Mat(foreground.size(), CvType.CV_8UC1,
new Scalar(255, 255, 255));
Imgproc.cvtColor(foreground, mask, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(mask, mask, 254, 255, Imgproc.THRESH_BINARY_INV);
Mat vals = new Mat(1, 1, CvType.CV_8UC3, new Scalar(0.0));
background.copyTo(dst);
background.setTo(vals, mask);
Core.add(background, foreground, dst, mask);
Bitmap grabCutImage = Bitmap.createBitmap(dst.cols(), dst.rows(), Bitmap.Config.ARGB_8888);
Bitmap processedImage = Bitmap.createBitmap(dst.cols(), dst.rows(), Bitmap.Config.RGB_565);
Utils.matToBitmap(dst, grabCutImage);
dst.copyTo(sampleImage);
imageView.setImageBitmap(grabCutImage);
firstMask.release();
source.release();
bgModel.release();
fgModel.release();
}

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 - FloodFill doesn't change mask image

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;

rectangle region segmentation

I'm trying to get the red rectangle region below "C", as image below:
And below is my source code use Opencv4Android:
public void threshold() {
Mat rgbMat = new Mat();
Mat grayMat = new Mat();
Mat edgeMat = new Mat();
Utils.bitmapToMat(bmp, rgbMat);
Mat intermediate = new Mat();
Imgproc.cvtColor(rgbMat, intermediate, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(intermediate, intermediate, new Size(3, 3), 0);
Imgproc.threshold(intermediate, intermediate, 190, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
Imgproc.Canny(intermediate, intermediate, 60, 140);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat mHierarchy = new Mat();
Imgproc.findContours(intermediate, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
Scalar CONTOUR_COLOR = new Scalar(255,0,0,255);
Log.e(TAG, "Contours count: " + contours.size());
Imgproc.drawContours(intermediate, contours, -1, CONTOUR_COLOR);
Bitmap edgeBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Config.ARGB_8888);
Utils.matToBitmap(intermediate, edgeBmp);
imageView.setImageBitmap(edgeBmp);
}
but the result is not as I expected: as image below:
As log show, Contours count: 372, and the rectangle region is discontinuous, How can I get the contour of the red rectangle region, and filter another useless region. I have referenced some other questions, but the question still not be solved, Could you do me a favor?
[update] change the code by the suggest from Morotspaj,
public void thresholdNew() {
Mat rgbMat = new Mat();
Mat grayMat = new Mat();
Utils.bitmapToMat(bmp, rgbMat);
Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_BGR2GRAY);
Vector<Mat> bgr_planes = new Vector<Mat>();
Core.split(rgbMat, bgr_planes);
Mat redMat = bgr_planes.get(2);
Mat redness = new Mat();
Core.subtract(redMat, grayMat, redness);
Mat intermediateMat1 = new Mat();
Mat intermediateMat2 = new Mat();
Imgproc.GaussianBlur(redness, intermediateMat1, new Size(15,15), 0);
Imgproc.GaussianBlur(redness, intermediateMat2, new Size(55,55), 0);
Mat red_mask = new Mat();
Core.subtract(intermediateMat1, intermediateMat2, red_mask );
Imgproc.threshold(red_mask , red_mask , 90, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
Mat masked_image = rgbMat.clone();
masked_image = masked_image.setTo(new Scalar(255,0,0), red_mask );
Bitmap edgeBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Config.ARGB_8888);
Utils.matToBitmap(masked_image, edgeBmp);
imageView.setImageBitmap(edgeBmp);
}
But the result is not as I expected and different with Morotspaj's.
Any error exist in the above code?
[update] Sorry, I am very busy these days, I will be try again later, and If I can not implement with Java, I will use Morotspaj's code through JNI. I will be update soon.
I made a filter to mask out the red rectangle region, just for you ;)
Mat rgbMat = imread("red_rectangle.jpg", -1);
Mat grayMat;
cvtColor(rgbMat, grayMat, COLOR_BGR2GRAY);
// Separate the red channel and compare it to the gray image
Mat channels[3];
split(rgbMat, channels);
Mat redness = Mat_<float>(channels[2]) - Mat_<float>(grayMat);
// Find the sharp red region
Mat red_blur1;
Mat red_blur2;
GaussianBlur(redness, red_blur1, Size(15,15), 0);
GaussianBlur(redness, red_blur2, Size(55,55), 0);
Mat red_mask = (red_blur1-red_blur2) > 2;
// Store result
Mat masked_image = rgbMat.clone();
masked_image.setTo(Scalar(0,0,255), red_mask);
imwrite("red_mask.png", red_mask);
imwrite("masked_image.png", masked_image);
The GaussianBlur method calls can be replaced by boxFilter if you need better performance, and the constants here and there can of course be tweaked. Hope this helps!
EDIT: Taking the difference of two differently blurred images is known as Difference of Gaussians (DoG). It finds changes in a certain scale depending on the size of the kernels. The smaller kernel is used to smooth away small details and noise. The bigger kernel destroys the details we are interested in but not the regions with very smooth changes that we don't want. By taking the difference between them we end up with only the details in the scale we are interested in! A mask can then be created easily by thresholding with the > operator.

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