I try to only detect eyes inside the face rectangle. Eyes are actually only detected, when there is an face recognized, but the corresponding rectangle are misplaced:
The green rectangle correctly catches the face. But the cyan-colored eye rectangles are misplaced to the top left. Seems they are originating from coords 0,0 and not from the top-left corner of the face rectangle.
// detect faces
this.faceCascade.detectMultiScale(grayFrame, faces, 1.1, 2, 0 | Objdetect.CASCADE_SCALE_IMAGE, new Size(this.absoluteFaceSize, this.absoluteFaceSize), new Size());
Rect[] facesArray = faces.toArray();
MatOfRect eyes = new MatOfRect();
this.eyeCascade.load("resources/haarcascades/haarcascade_eye.xml");
for (int i = 0; i < facesArray.length; i++) {
Rect currentFace = facesArray[i];
Imgproc.rectangle(frame, currentFace.tl(), currentFace.br(), new Scalar(0, 255, 0), 3);
Imgproc.putText(frame, "face", currentFace.tl(), 2, 2, new Scalar(0, 255, 0));
Mat faceROI = grayFrame.submat(currentFace);
this.eyeCascade.detectMultiScale(faceROI, eyes, 1.1,2,0 | Objdetect.CASCADE_SCALE_IMAGE, new Size(this.absoluteFaceSize/5, this.absoluteFaceSize/5), new Size());
Rect[] eyesArray = eyes.toArray();
for (Rect eye : eyesArray) {
Point tl = new Point(currentFace.x+eye.tl().x, currentFace.y+eye.tl().y);
Point br = new Point(currentFace.x + eye.br().x, currentFace.y + eye.br().y);
Imgproc.rectangle(faceROI, tl, br, new Scalar(0, 0, 255), 3);
Imgproc.putText(faceROI, "Eye", tl, 2, 2, new Scalar(0, 0, 255));
}
}
Related
I have to take shelf plans. I would like to order them as if it were a matrix where [0,0] was at the bottom left or top left.
I need this because there will be a database with coordinates to take something on the shelf.
But findContours takes the contours randomly and I don't know how to sort them.
How can I do?
I hope I was clear.
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
Mat img = inputFrame.rgba();
Imgproc.cvtColor(img, gray, Imgproc.COLOR_BGR2GRAY, 0);
Imgproc.Canny(gray, gray, 100, 255, 3, true);
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, kernelSize);
Imgproc.dilate(gray, gray, kernel);
Imgproc.GaussianBlur(gray, gray, new Size(3, 3), 0);
List < MatOfPoint > contours = new ArrayList < MatOfPoint > ();
Imgproc.findContours(gray, contours, hierarchy, Imgproc.RETR_TREE,
Imgproc.CHAIN_APPROX_SIMPLE);
MatOfPoint2f approxCurve = new MatOfPoint2f();
//For each contour found
for (int i = 0; i < contours.size(); i++) {
//convert contours(i) from MatOfPoint to MatOfPoint2f
MatOfPoint2f contour2f = new
MatOfPoint2f(contours.get(i).toArray());
double approxDistance = Imgproc.arcLength(contour2f, true) * 0.05;
Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);
//convert back to MatOfPoint
MatOfPoint points = new MatOfPoint(approxCurve.toArray());
//SORT POINTs
//Get bounding rect of contour
Rect rect = Imgproc.boundingRect(points);
//draw enclosing rectangle
if (rect.height > 200 && rect.width > 200)
// Imgproc.rectangle(img,new Point(rect.x,rect.y),new
Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 0, 255), 4);
Imgproc.rectangle(img, rect.tl(), rect.br(), new Scalar(0, 0, 255), 4);
}
return img;
}
public BufferedImage detectAndDisplay(BufferedImage img, CascadeClassifier faceCascade) {
Mat frameGray = new Mat();
BufferedImage imgout = null;
Mat image = ImagePreProcessing.bufferedImageToMat(img);
// -- Detect faces
MatOfRect faces = new MatOfRect();
faceCascade.detectMultiScale(image, faces);
List<Rect> listOfFaces = faces.toList();
for (Rect face : listOfFaces) {
Point center = new Point(face.x + face.width / 2, face.y + face.height / 2);
Imgproc.ellipse(image, center, new Size(face.width / 2, face.height / 2), 0, 0, 360,
new Scalar(255, 0, 255), 3);
Mat faceROI = image.submat(face);
imgout = ImagePreProcessing.Mat2BufferedImage(faceROI);
System.out.println("OpenCV: " +center);
}
return imgout;
}
that code I have..but I don't know where the code for setting crop output image.
I want to have the picture like original version with circle template..NOT to be crop
Can give me suggestion, please:)
input:
output:
In your code, you returned a cropped image of the original image, so if you want the original image, draw the circle and convert it to the BufferedImage and return.
for (Rect face : listOfFaces) {
Point center = new Point(face.x + face.width / 2, face.y + face.height / 2);
Imgproc.ellipse(image, center, new Size(face.width / 2, face.height / 2), 0, 0, 360,
new Scalar(255, 0, 255), 3);
// dot not crop!!!
/*Mat faceROI = image.submat(face);
imgout = ImagePreProcessing.Mat2BufferedImage(faceROI);*/
System.out.println("OpenCV: " +center);
imgout = ImagePreProcessing.Mat2BufferedImage(image);
}
I'm new to OpenCV, and I want to work on object detection to help my FRC robotics team. I'm trying to use an HSV filter and HoughCircles to find a tennis ball in a webcam image and draw a circle around it. Here is my code:
Mat currentFrame = new Mat();
Mat hsv = new Mat();
Mat threshImage = new Mat();
Mat circles = new Mat();
while (true) {
camera.read(currentFrame);
Imgproc.resize(currentFrame, currentFrame, new Size(WIDTH, HEIGHT));
Imgproc.cvtColor(currentFrame, hsv, Imgproc.COLOR_RGB2HSV);
hsvWindow.showImage(hsv);
Core.inRange(hsv, new Scalar(50, 100, 0), new Scalar(95, 255, 255), threshImage);
threshWindow.showImage(threshImage);
Imgproc.HoughCircles(threshImage, circles, Imgproc.CV_HOUGH_GRADIENT, 2, 100, 100, 100, 0, 500);
for (int i = 0; i < circles.cols(); i++) {
double[] vCircle = circles.get(0, i);
Point pt = new Point(Math.round(vCircle[0]), Math.round(vCircle[1]));
int radius = (int)Math.round(vCircle[2]);
Core.circle(currentFrame, pt, radius, new Scalar(255, 0, 0), 2);
}
drawWindow.showImage(currentFrame);
}
The original image, the hsv image, and the filtered image are in this album: http://imgur.com/a/hO8vs
When I run HoughCircles with the parameters here, it finds circles on the piano bench and toy rabbit, but not the tennis ball, which appears as a big white circle.
I fixed it! After some fiddling with the parameters of HoughCircles and blurring and thresholding the binary image it was finding it reliably, but the circle was jittery and inconsistent. So, I replaced HoughCircles with findContours, cycled through the contours looking for the largest one, and used minEnclosingCircle. Here is the code now:
Mat currentFrame = new Mat(), hsv = new Mat(), threshImage = new Mat();
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
while (true) {
camera.read(currentFrame);
Imgproc.resize(currentFrame, currentFrame, new Size(WIDTH, HEIGHT));
Imgproc.cvtColor(currentFrame, hsv, Imgproc.COLOR_RGB2HSV);
hsvWindow.showImage(hsv);
Core.inRange(hsv, new Scalar(50, 100, 50), new Scalar(95, 255, 255), threshImage);
Imgproc.blur(threshImage, threshImage, new Size(10, 10));
Imgproc.threshold(threshImage, threshImage, 150, 255, Imgproc.THRESH_BINARY);
threshWindow.showImage(threshImage);
Imgproc.findContours(threshImage, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
double maxArea = 0;
float[] radius = new float[1];
Point center = new Point();
for (int i = 0; i < contours.size(); i++) {
MatOfPoint c = contours.get(i);
if (Imgproc.contourArea(c) > maxArea) {
MatOfPoint2f c2f = new MatOfPoint2f(c.toArray());
Imgproc.minEnclosingCircle(c2f, center, radius);
}
}
Core.circle(currentFrame, center, (int)radius[0], new Scalar(255, 0, 0), 2);
drawWindow.showImage(currentFrame);
}
I know this might not be particularly helpful for people looking to use HoughCircles specifically, but it's a testament to the power of blurring binary images. If you're looking for a circle among many things, you look for contours and compare the contour area to the area of its enclosing circle.
I wrote the below code to draw lines to link the corners of the object image, what I want to do is to draw lines to link the corners of the scene image.
the object is placed on the left side, and the scene is on the right side, and since I have the points of the corners of the object, I think I need just to add the points of the object corners so that:
top left sceneCorner : objCorners.cols
top right sceneCorner: objCorners.cols * 2
bottom right sceneCorner: objCorners.rows * 2
bottom left scenecorner: objCorners.rows
now i do not know how to add these coordinates to draw lines link the scene corners?
code:
Mat objCorners = new Mat(4, 1, CvType.CV_32FC2);
Mat sceneCorners = new Mat(4, 1, CvType.CV_32FC2);
objCorners.put(0, 0, new double[] {0, 0});//top left
objCorners.put(1, 0, new double[] {matFactory.getMatAt(0).cols(), 0});//top right
objCorners.put(2, 0, new double[] {matFactory.getMatAt(0).cols(), matFactory.getMatAt(0).rows()});//bottom right
objCorners.put(3, 0, new double[] {0, matFactory.getMatAt(0).rows()});//bottom left.
sceneCorners.put(0, 0, new double[] {0, 0});//top left
sceneCorners.put(1, 0, new double[] {matFactory.getMatAt(1).cols(), 0});//top right
sceneCorners.put(2, 0, new double[] {matFactory.getMatAt(1).cols(), matFactory.getMatAt(1).rows()});//bottom right
sceneCorners.put(3, 0, new double[] {0, matFactory.getMatAt(1).rows()});//bottom left.
Log.D(TAG, "", "sceneCorners.size: " + sceneCorners.dump());
Log.D(TAG, "", "objCorners.size: " + objCorners.dump());
Core.perspectiveTransform(objCorners, sceneCorners, H);// the values inside sceneCorners matrix changes after this line as it is what this function returns.
Log.D(TAG, "", "sceneCorners.size: " + sceneCorners.dump());
Log.D(TAG, "", "objCorners.size: " + objCorners.dump());
//the below 4 lines are to draw line links between the objCorners.
Core.line(outImg, new Point(objCorners.get(0, 0)), new Point(objCorners.get(1, 0)), new Scalar(0, 0, 255), 4);
Core.line(outImg, new Point(objCorners.get(1, 0)), new Point(objCorners.get(2, 0)), new Scalar(0, 0, 255), 4);
Core.line(outImg, new Point(objCorners.get(2, 0)), new Point(objCorners.get(3, 0)), new Scalar(0, 0, 255), 4);
Core.line(outImg, new Point(objCorners.get(3, 0)), new Point(objCorners.get(0, 0)), new Scalar(0, 0, 255), 4);
MatFactory.writeMat(FilePathUtils.newOutputPath("corners"), outImg);
I am working on AndEngine, and stuck to know the exact height and width of the PhysicsWorld which I used in meters.
this.mScene = new Scene();
this.mScene.setBackground(new Background(0, 0, 0));
this.mScene.setOnSceneTouchListener(this);
this.mScene.setOnAreaTouchListener(this);
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, 10), false);
this.mScene.registerUpdateHandler(this.mPhysicsWorld);
I solved it in my way.. thank you #LearnCocos2D.
this.mScene = new Scene();
this.mScene.setBackground(new Background(0, 0, 0));
this.mScene.setOnSceneTouchListener(this);
this.mScene.setOnAreaTouchListener(this);
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, 10), false);
this.mScene.registerUpdateHandler(this.mPhysicsWorld);
final Rectangle ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2, vertexBufferObjectManager);
final Rectangle left = new Rectangle(0, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
final Rectangle right = new Rectangle(CAMERA_WIDTH - 2, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
Body g =PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef2);
Body l =PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef1);
final float width = 2*g.getWorldCenter().x;
final float height = 2*l.getWorldCenter().y;