I'm trying to blur the faces of all people detected by the webcam.
The problem is that when the webcam detect a face the program shows the crop mat with the blur face.
I tried to put the blur face into the original mat but it doesn't work.
for(Rect rect : faces.toArray()){
Imgproc.rectangle(frame, rect.tl(), rect.br(), new Scalar(0,0,255),3);
Rect rectCrop = new Rect(rect.x, rect.y , rect.width, rect.height);
Mat imageROI = grayFrame.submat(rectCrop);
//frame is the original mat with the correct size
Imgproc.GaussianBlur(imageROI, frame, new Size(55, 55), 55);
}
No face detection:
With face detection:
use this constructor of Mat
Mat imageROI = new Mat(grayFrame,rectCrop);
instead of
Mat imageROI = grayFrame.submat(rectCrop);
The constructor gives you reference to the data matrix that is owned by grayFrame. so any modifications to submat will effect the bigmat.The submat gives copy of the grayFrame data matrix for the crop rectangle. So the modifications on the submat will not effect the bigmat.
Related
I'm trying to develop an application with android studio to capture the color of flashing LEDs.
Im now at this Point, that i got the positions of the LEDs and now i want to determine the bounding box center with the class moments of openCV.
Mat src = new.Mat(Bitmap.getHeight(), Bitmap.getWidth(), CvType.CV_8UC1);
Mat hsv = new Mat();
Utils.bitmapToMat(Bitmap, src);
Imgproc.cvtColor(src,hsv, Imgproc.COLOR_BGR2HSV);
Core.inRange(hsv,LOWER_RED,HIGHER_RED,hsv);
Imgproc.dilate(hsv,hsv,Imgproc.getStructuringElement(Imgproc.MORPH_VECT,new Size(50,50)));
List<MatOfPoint> contours = new ArrayList <>();
Mat hierarchy = new Mat();
Imgproc.findContours(hsv, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
hierarchy.release();
//finding Bounding Box Center
List<Moments> mu = new ArrayList<>(contours.size());
mu.add(1, Imgproc.moments(contours.get(1), false));
Utils.matToBitmap(hsv,Bitmap);
//...
And the lines with Moments brings me following error message:
No implementation found for double[] org.opencv.imgproc.Imgproc.moments_0(long, boolean) ( tried Java_org_opencv_imgproc_Imgproc_moments_10 and Java_org_opencv_imgproc_Imgproc_moments_10__JZ )
So if i jump to Imgproc.java then the method is red marked and following message popups by mouseover:
Cannot resolve corresponding JNI function Java_org_opencv_imgproc_Imgproc_moments_10
Reports native method declaration in Java where no corresponding JNI functions is found in the project.
Thanks for reading
Can anyone help me ?
I'm trying to detect skin on images using opencv (new at it) but I've managed to get SOME of the skin to be detected, however the rest seems to cause some noise on the image. Here's the original image:
The result of my code is:
The code that prouduces this:
Mat image = Imgcodecs.imread(name);
Imgproc.pyrMeanShiftFiltering(image, image, 10, 20);
Imgproc.blur(image, image, new Size(3, 3));
Mat hsv = new Mat();
Imgproc.cvtColor(image, hsv, Imgproc.COLOR_BGR2HSV);
Mat bw = new Mat();
Core.inRange(hsv, new Scalar(0, 10, 60), new Scalar(20, 150, 255), bw);
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(bw, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_NONE, new Point(0, 0));
int s = findBiggestContour(contours);
Mat drawing = new Mat(image.size(), CvType.CV_8UC1);
Imgproc.drawContours(drawing, contours, s, new Scalar(255), -1, 8, hierarchy, 0, new Point(0, 0));
Imgcodecs.imwrite(rename(name), drawing);
How do I fix the code to detect the remaining skin on the image and get rid of the noise?
I'm using Java with OpenCV 3.0.0.
Since you're using the findBiggestConour() I think you only draw the biggest match, not all of them. Since the biggest contour happens to be the one on the second image only that is shown.
Just to add to what JanSLO said here above, I tried your code and instead of drawing just the biggest contour, I drew all contours and got the following result.
//c++ code, not java
Mat drawing = Mat::zeros(img.size(), CV_8UC1 );
for(int i=0; i < contours.size(); ++i) {
drawContours(drawing, contours, i, Scalar(255), 3, 8, hierarchy, 0, Point(0, 0));
}
imwrite("data/skin_detect_out.jpg", drawing);
I am pleasantly surprised at the result, since this is such a simple piece of code. More advanced pixel based skin detection methods involve making a probability model of skin pixels using training data, and using that model to classify whether a given pixel is skin or not.
I want to get all the outer contours with RETR_EXTERNAL but for some weird reason openCV thinks that the image border is a contour too and therefore discards all inner contours. What exactly am I doing wrong here?
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(imageA, contours, hierarchy, Imgproc.RETR_EXTERNAL,
Imgproc.CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++) {
double[] c = hierarchy.get(0, i);
Rect rect = Imgproc.boundingRect(contours.get(i));
Core.rectangle(image, new Point(rect.x, rect.y),
new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 255, 0), 3);
}
Input (imageA was processed to this before contour-finding):
Output:
EDIT:
Problem partially solved
Inverting the pixels so that black is the background and white the foreground helped with the image above image. However I still get inner contours on some images. Like this one:
Input
Output
Your input image isnt good enought o extract the contours you want to have.
Your input contours are these (part of your image):
each color is a single contour (and some of the white ones)
For the red contour I've drawn the bounding rectangle which is the same method that you used to display the contours. All the other colored contours aren't inside of the red contour, but just inside of the bounding rectangle, that's why they are found even though you selected to only find the outer contours.
What you really want is something like this:
but to get that result, your input image must have that lines of the ellipse connected, too!!
For your input image it will be very hard to extract those lines, without getting lines of the ground too, but an easy approach could be to use a couple of dilation operations followed by the same number of erosion operations on your input image, before extracting contours. This won't be stable for all setting though ;)
I'm currently working on a program that should draw a small image onto the camera frame. With Android OpenCV, you do have the following function to process a frame:
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Mat rgba = inputFrame.rgba();
mDetector.setFrame(rgba);
mDetector.processFrame();
return rgba;
}
Where the Mat rgba then gets displayed on the screen. My Detector should now process the frame rgba (change it).
Here is the relevant code:
public void processFrame() {
// (1) Doesn't work
Rect roi = new Rect(0, 0, 100, 100);
Mat submat = mOutputFrame.submat(roi);
Mat image = new Mat(100, 100, CvType.CV_8UC3, new Scalar(0,0,0));
image.copyTo(submat);
// (2) Does work
// --- mComparatorImage is the same size as mOutputFrame.
// --- mComparatorImage is 8bit greyscale, mOutputFrame is the rgba CameraFrame
mComparatorImage = mComparatorHolder.getCurrentImage();
mComparatorImage.copyTo(mOutputFrame);
// (3) Should work (but doesn't)
Imgproc.resize(mComparatorImage, mResizedImageClone, new Size (200, 100));
Mat bSubmat = mOutputFrame.submat(new Rect(0, 0, 200, 100));
mResizedImageClone.copyTo(bSubmat);
}
What I'm trying to do is to copy a resized version of mComparatorImage into the camera frame that is referenced by mOutputFrame (mOutputFrame = rgba).
So I tried doing (3).
FYI: mResizedImageClone is of type Mat and is initialized as a new Mat()
Doing (3) doesn't change the mOutputFrame.
(2) Then I tried copying the whole mComparatorImage (type Mat and same size as mOutputFrame) to mOutputFrame. This worked suprisingly.
(1) Then I thought the problem has to be something with submat, because copying the big image works, but copying a small version of it into mOutputFrame doesnt. So I tried copying a little black image into mOutputFrame. This doesn't work either, although I followed other answers here.
What could be the problem? There is no error, but the camera frame stays the same in (1) and (3)
If you need any additional info, let me know.
Isa
Okay, I've found it, it was a little bit tricky.
The copyTo function using submatrices works only properly if the src and the dest Mat are of the same type. Otherwise, it just does ... nothing. (It rather should complain!)
Instead of using rect, I used submat with parameters (row_start, row_end, col_start, col_end)
Also be aware that the dimensions of the submat (#cols and #rows) have to exactly match the src image that is used in copyTo.
So here is my solution for (1):
// (1) Inserting a little black rect into the camera frame:
Mat submat = mOutputFrame.submat(0, 100, 0, 100);
Mat image = new Mat(100, 100, mOutputFrame.type(), new Scalar(0,0,0));
image.copyTo(submat);
And my solution for (3):
// (3) Resizing and inserting an arbitrary grey image into the rgba camera frame
Imgproc.resize(mComparatorImage, mResizedImageClone, new Size (200, 100));
Imgproc.cvtColor(mResizedImageClone, mResizedImageClone, Imgproc.COLOR_GRAY2RGBA);
Mat submat = mOutputFrame.submat(0, 100, 0, 200);
mResizedImageClone.copyTo(submat);
I am developing an Android app that calculates the sum of all points of the being-seen dominoes pieces -shown in picture- using OpenCV for Android.
The problem is, I can't find a way to filtering other contours and counting only dots I see in the dominoes, I tried to use Canny edge finding then use HoughCircles, but with no result, as I don't have an absolute top view of the rocks and HoughCircles detect perfect circles only :)
Here is my code:
public Mat onCameraFrame(Mat inputFrame) {
inputFrame.copyTo(mRgba);
Mat grey = new Mat();
// Make it greyscale
Imgproc.cvtColor(mRgba, grey, Imgproc.COLOR_RGBA2GRAY);
// init contours arraylist
List<MatOfPoint> contours = new ArrayList<MatOfPoint>(200);
//blur
Imgproc.GaussianBlur(grey, grey, new Size(9,9), 10);
Imgproc.threshold(grey, grey, 80, 150, Imgproc.THRESH_BINARY);
// because findContours modifies the image I back it up
Mat greyCopy = new Mat();
grey.copyTo(greyCopy);
Imgproc.findContours(greyCopy, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_NONE);
// Now I have my controus pefectly
MatOfPoint2f mMOP2f1 = new MatOfPoint2f();
//a list for only selected contours
List<MatOfPoint> SelectedContours = new ArrayList<MatOfPoint>(400);
for(int i=0;i<contours.size();i++)
{
if(here I should put a condition that distinguishes my spots, eg: if contour inside is black and is a black disk)
{
SelectedContours.add(contours.get(i));
}
}
Imgproc.drawContours(mRgba, SelectedContours, -1, new Scalar(255,0,0,255), 1);
return mRgba;
}
EDIT:
One unique feature of my contours after threshold is they're totally black from inside, is there anyway I could calculate the mean color/intensity for a given contour ?
There is a similiar problem and possible solution on SO, titled Detection of coins (and fit ellipses) on an image. Here you will find some recomendations about opencv's function fitEllipse.
You should take a look at this for more info on opencv's function fitEllipse.
Also, to detect only black elements in an image, you can use HSV color model, to find only black colors. You can find an explanation here.