How to setting cropping size in CascadeCalssifier with Java - java

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);
}

Related

How can I order the contours in an orderly manner from top to bottom from left to right?

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;
}

OpenCV: Rects for eyes are displaced from face ROI

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));
}
}

Finding image in specific area in image using Matching Template in javacv

I am trying to find the location of image inside a specific area in another. I am using javacv to do this issue. But my code is giving an error when executing cvMatchTemplate function. I think I am miss using cvSetImageROI.
This is how I am using it:
public static void main(String c[]) {
IplImage src = cvLoadImage("test.jpg", 0);
IplImage tmp = cvLoadImage("tmp.png", 0);
IplImage result = cvCreateImage(cvSize(src.width() - tmp.width() + 1, src.height() - tmp.height() + 1),
IPL_DEPTH_32F,1);
cvZero(result);
cvSetImageROI(src, new CvRect(22, 50, 30, 30));
cvSetImageROI(result, new CvRect(22, 50, 30, 30));
//Match Template Function from OpenCV
cvMatchTemplate(src, tmp, result, CV_TM_CCORR_NORMED);
double[] min_val = new double[2];
double[] max_val = new double[2];
CvPoint minLoc = new CvPoint();
CvPoint maxLoc = new CvPoint();
cvMinMaxLoc(result, min_val, max_val, minLoc, maxLoc,
null);
CvPoint point = new CvPoint();
point.x(maxLoc.x() + tmp.width());
point.y(maxLoc.y() + tmp.height());
cvRectangle(src, maxLoc, point, CvScalar.RED, 2, 8, 0);
cvShowImage("Lena Image", src);
cvWaitKey(0);
cvReleaseImage(src);
cvReleaseImage(tmp);
cvReleaseImage(result);
}
This is the error:
OpenCV Error: Assertion failed (result.size() == cv::Size(std::abs(img.cols - templ.cols)
+ 1,std::abs(img.rows - templ.rows) + 1) && result.type() == CV_32F) in unknown function,
file ..\..\..\src\opencv\modules\imgproc\src\templmatch.cpp, line 384
Any Help?
Hey see this example that I did with Javacv
public class Test {
static Image image;
public static void main(String[] args) throws Exception {
int width = Integer.parseInt(args[3]);
int height = Integer.parseInt(args[4]);
IplImage src = cvLoadImage(
args[0], 0);
IplImage tmp = cvLoadImage(
args[1], 0);
IplImage result = cvCreateImage(
cvSize(src.width() - tmp.width() + 1,
src.height() - tmp.height() + 1), IPL_DEPTH_32F, src.nChannels());
cvZero(result);
// Match Template Function from OpenCV
cvMatchTemplate(src, tmp, result, CV_TM_CCORR_NORMED);
// double[] min_val = new double[2];
// double[] max_val = new double[2];
DoublePointer min_val = new DoublePointer();
DoublePointer max_val = new DoublePointer();
CvPoint minLoc = new CvPoint();
CvPoint maxLoc = new CvPoint();
cvMinMaxLoc(result, min_val, max_val, minLoc, maxLoc, null);
// Get the Max or Min Correlation Value
// System.out.println(Arrays.toString(min_val));
// System.out.println(Arrays.toString(max_val));
CvPoint point = new CvPoint();
point.x(maxLoc.x() + tmp.width());
point.y(maxLoc.y() + tmp.height());
// cvMinMaxLoc(src, min_val, max_val,0,0,result);
cvRectangle(src, maxLoc, point, CvScalar.RED, 2, 8, 0);// Draw a
// Rectangle for
// Matched
// Region
CvRect rect = new CvRect();
rect.x(maxLoc.x());
rect.y(maxLoc.y());
rect.width(tmp.width() + width);
rect.height(tmp.width() + height);
cvSetImageROI(src, rect);
IplImage imageNew = cvCreateImage(cvGetSize(src), src.depth(),
src.nChannels());
cvCopy(src, imageNew);
cvSaveImage(args[2], imageNew);
cvShowImage("Lena Image", src);
cvWaitKey(0);
cvReleaseImage(src);
cvReleaseImage(tmp);
cvReleaseImage(result);
}
full reference here
we need 4 default parameters like this
"C:\Users\Waldema\Desktop\bg.jpg" "C:\Users\Waldema\Desktop\logosiemens.jpg" "C:\Users\Waldema\Desktop\imageToFind.jpg" 100 200
configurable in the Run configurations of common IDEs.
I think that will help
I found the problem it was in setting the roi of the result image, this is the wrong line :
cvSetImageROI(result, new CvRect(22, 50, 30, 30));
It should be like this :
cvSetImageROI(result, new CvRect(22, 50, 30 - tmp.width() + 1, 30 - tmp.height() + 1));
I am not sure why but I think it is because cvMatchTemplate function takes the result dimension equal to the source dimensions minus the template dimensions plus one pixel.

Adding a round frame circle on rounded bitmap

Im trying to create a round frame around my bitmap!
With this code im able to make my bitmap round:
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff4242DB;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = bitmap.getWidth()/2;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
//canvas.drawCircle(0, 0, bitmap.getWidth(), paint);
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
What i've tried is to draw a circle(the outcommented line) with canvas, but It had no result.
Does anyone know how I can add a circular border around it?
EDIT
When I use the line:
canvas.drawCircle(0, 0, bitmap.getWidth(), paint);
The effect is, that 3 corners get rounded but the upper left stays the same(90 degrees)
But I can't see any line or circle!
Update
There now is RoundedBitmapDrawable and a corresponding factory in the Support library I recommend to use that, unless more flexibility is required.
Original Answer
You have to draw the circle after the bitmap. This is what did the trick for me.
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int radius = Math.min(h / 2, w / 2);
Bitmap output = Bitmap.createBitmap(w + 8, h + 8, Config.ARGB_8888);
Paint p = new Paint();
p.setAntiAlias(true);
Canvas c = new Canvas(output);
c.drawARGB(0, 0, 0, 0);
p.setStyle(Style.FILL);
c.drawCircle((w / 2) + 4, (h / 2) + 4, radius, p);
p.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
c.drawBitmap(bitmap, 4, 4, p);
p.setXfermode(null);
p.setStyle(Style.STROKE);
p.setColor(Color.WHITE);
p.setStrokeWidth(3);
c.drawCircle((w / 2) + 4, (h / 2) + 4, radius, p);
return output;
This does of course not include the fancy shadow of your example.
You might want to play around a little bit with the additional pixels.

OCR with javacv

I am making an OCR for my project and stuck on a point, Right now i am performing segmentation on the basis of contours its working fine with few images but there few more where it fails even when the image quality is good, I would appreciate if someone suggest me more accurate way, and if someone provide a code example, here is my current code.
public static void imageBinarization(IplImage src, IplImage dst){
IplImage r, g, b, s;
r = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
g = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
b = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvSplit(src, r, g, b, null);
s = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvAddWeighted(r, 1./3., g, 1./3., 0.0, s);
cvAddWeighted(s, 2./3., b, 1./3., 0.0, s);
cvThreshold(s, dst, 100, 100, CV_THRESH_BINARY_INV);
cvReleaseImage(r);
cvReleaseImage(g);
cvReleaseImage(b);
cvReleaseImage(s);
}
public static void imageSegmentation(String sourcePath, String targetPath){
cvConvert(t0, mat0);
cvConvert(t8, mat8);
cvConvert(t9, mat9);
IplImage image = cvLoadImage(sourcePath);
IplImage grayImage = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
//cvSmooth(image, image, CV_BLUR_NO_SCALE, 2);
//cvSmooth(image, image, CV_BLUR, 9, 9, 2, 2);
//cvSmooth(image, image, CV_GAUSSIAN, 3);
imageBinarization(image, grayImage);
CvMemStorage mem;
CvSeq contours = new CvSeq();
CvSeq ptr = new CvSeq();
mem = cvCreateMemStorage(0);
CvRect rect = null;
int px1,px2, py1, py2;
CvScalar blue = CV_RGB(0, 0, 250);
int n = 0; int i = 0;
cvFindContours(grayImage, mem, contours, sizeof(CvContour.class) , CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
Random rand = new Random();
for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
Color randomColor = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
CvScalar color = CV_RGB( randomColor.getRed(), randomColor.getGreen(), randomColor.getBlue());
rect = cvBoundingRect(ptr, n);//new CvRect(cvGetSeqElem(c, c.total()));
px1 = rect.x(); py1 = rect.y(); px2 = (rect.x() + rect.width()); py2 = (rect.y() + rect.height());
cvRectangle(image, cvPoint(px1, py1), cvPoint(px2, py2), blue, 1, CV_AA, 0);
//----
xbox = rect.x(); ybox = rect.y(); wbox = rect.width(); hbox = rect.height();
img = cvCreateImage(cvSize(wbox, hbox), image.depth(), image.nChannels());
cvSetImageROI(image, cvRect(xbox, ybox, wbox, hbox));
cvCopy(image, img);
cvResetImageROI(image);
//cvSaveImage(targetPath+i+".jpg", img);
i++;
//---
//cvDrawContours(image, ptr, color, CV_RGB(0,0,0), -1, CV_FILLED, 8, cvPoint(0,0));
}
cvSaveImage(targetPath+"mat.jpg", image);
}
Try to use some Global Thresholding algorithm such as Otsu. But JavaCV haven't implemented that. So try to find the Otsu threshold level using histogram processing and apply that value to
cvThreshold(s, dst, 100, 100, CV_THRESH_BINARY_INV);

Categories

Resources