Opencv(3.10) android- How to draw an object's trajectory - android

I have a project in college where I have to draw the trajectory of an object based on the color of it. Is being built based on colorBlobDetection. This is part of the code I have so far:
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
if (mIsColorSelected) {
mDetector.process(mRgba);
List<MatOfPoint> contours = mDetector.getContours();
Log.e(TAG, "Contours count: " + contours.size());
Imgproc.drawContours(mRgba, contours, -1, CONTOUR_COLOR);
List<Moments> mu = new ArrayList<Moments>(contours.size());
for (int i = 0; i < contours.size(); i++) {
mu.add(i, Imgproc.moments(contours.get(i), false));
Moments p = mu.get(i);
int xContour = (int) (p.get_m10() / p.get_m00());
int yContour = (int) (p.get_m01() / p.get_m00());
Point ponto = new Point(xContour, yContour);
//Imgproc.line(mRgba, ponto, ponto, CONTOUR_COLOR, 5, Imgproc.LINE_AA, 0);
}
At the moment I'm picking up the center of each contour.
Through the positions of the contours I want to draw their trajectories when they move
Ps. This 'Imgproc.line' was just to test if the center of each contour is correct.
Please help.

Related

Perspective Transform OpenCV

I'm new to OpenCV on Android and try to do Perspective Transform but I don't know how to use getperspectivetransform() and warpperspective() functions.I could detect rectangle from an image, but don't know how to warp.
Here is the detect rectangle function:
Mat tempMat = new Mat();
Mat src = new Mat();
Utils.bitmapToMat(image, tempMat);
Imgproc.cvtColor(tempMat, src, Imgproc.COLOR_BGR2RGB);
Mat blurred = src.clone();
Imgproc.medianBlur(src, blurred, 9);
Mat gray0 = new Mat(blurred.size(), CvType.CV_8U), gray = new Mat();
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
List<Mat> blurredChannel = new ArrayList<Mat>();
blurredChannel.add(blurred);
List<Mat> gray0Channel = new ArrayList<Mat>();
gray0Channel.add(gray0);
MatOfPoint2f approxCurve = new MatOfPoint2f();
double maxArea = 0;
int maxId = -1;
for (int c = 0; c < 3; c++) {
int ch[] = { c, 0 };
Core.mixChannels(blurredChannel, gray0Channel, new MatOfInt(ch));
int thresholdLevel = 1;
for (int t = 0; t < thresholdLevel; t++) {
if (t == 0) {
Imgproc.Canny(gray0, gray, 50, 50, 3, true); // true ?
Imgproc.dilate(gray, gray, new Mat(), new Point(-1, -1), 1); // 1
// ?
} else {
Imgproc.adaptiveThreshold(gray0, gray, thresholdLevel,
Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
Imgproc.THRESH_BINARY,
(src.width() + src.height()) / 200, t);
}
Imgproc.findContours(gray, contours, new Mat(),
Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
for (MatOfPoint contour : contours) {
MatOfPoint2f temp = new MatOfPoint2f(contour.toArray());
double area = Imgproc.contourArea(contour);
approxCurve = new MatOfPoint2f();
Imgproc.approxPolyDP(temp, approxCurve,
Imgproc.arcLength(temp, true) * 0.02, true);
if (approxCurve.total() == 4 && area >= maxArea) {
double maxCosine = 0;
List<Point> curves = approxCurve.toList();
for (int j = 2; j < 5; j++) {
double cosine = Math.abs(angle(curves.get(j % 4),
curves.get(j - 2), curves.get(j - 1)));
maxCosine = Math.max(maxCosine, cosine);
}
if (maxCosine < 0.45) {
maxArea = area;
maxId = contours.indexOf(contour);
}
}
}
}
}
I draw rectangle with this statement.
if (maxId >= 0) {
Rect rect = Imgproc.boundingRect(contours.get(maxId));
Imgproc.rectangle(src, rect.tl(), rect.br(), new Scalar(255, 0, 0,
.8), 4);
}
After that I convert mat to bitmap and show on an imageview.
Here is the screenshot
So my problem is warpping, How can I warp the rectangle and rotate it?
and If it is possible, how can I improve detecting rectangle? Any hints?
(OpenCV Android SDK Ver: 3.41, Android Studio Ver: 3.01)
If you are looking to warp the detected contour into rectangle,
Get the contours of the rectangle
find convex hull of the contour
Using approxPolyDP reduce the convex hull points into 4 points
fit line to consecutive points (ex, if pts is the array, lines are fit as follows l1 = line Between(pts[0], pts[1]), l2 = line Between(pts[1], pts[2]), l3 = line Between(pts[2], pts[3]), l4 = lineBetween(pts[3], pts[0])
find the intersection between these lines, you'll end up with four points
Order the points in clockwise order (inputCorners = TopLeft, TopRight, BottomRight, BottomLeft)
create an output image with needed resolution and make the corner points in the same clockwise order ((0,0), (0, cols), (rows, cols), (rows, 0))
find homography using the function
Mat homography = Calib3d.findHomography(inputCorners, imageCorners, Calib3d.RANSAC, 10);
using the output homography matrix, warp the input image using the function
Imgproc.warpPerspective(image, outputMat, homography, new Size(image.cols(), image.rows()));
you can refer to the following link
This is my kotlin extensin version you can use it in your projects.
fun Bitmap.perspectiveTransform(srcPoints: List<org.opencv.core.Point>) :
Bitmap{
val dstWidth = max(
srcPoints[0].distanceFrom(srcPoints[1]),
srcPoints[2].distanceFrom(srcPoints[3])
)
val dstHeight = max(
srcPoints[0].distanceFrom(srcPoints[2]),
srcPoints[1].distanceFrom(srcPoints[3])
)
val dstPoints: List<org.opencv.core.Point> = listOf(
org.opencv.core.Point(0.0, 0.0),
org.opencv.core.Point(dstWidth, 0.0),
org.opencv.core.Point(0.0, dstHeight),
org.opencv.core.Point(dstWidth, dstHeight)
)
return try {
val srcMat = Converters.vector_Point2d_to_Mat(srcPoints)
val dstMat = Converters.vector_Point2d_to_Mat(dstPoints)
val perspectiveTransformation =
Imgproc.getPerspectiveTransform(srcMat, dstMat)
val inputMat = Mat(this.height, this.width, CvType.CV_8UC1)
Utils.bitmapToMat(this, inputMat)
val outPutMat = Mat(dstHeight.toInt(), dstWidth.toInt(), CvType.CV_8UC1)
Imgproc.warpPerspective(
inputMat,
outPutMat,
perspectiveTransformation,
Size(dstWidth, dstHeight)
)
val outPut = Bitmap.createBitmap(
dstWidth.toInt(),
dstHeight.toInt(), Bitmap.Config.RGB_565
)
//Imgproc.cvtColor(outPutMat , outPutMat , Imgproc.COLOR_GRAY2BGR)
Utils.matToBitmap(outPutMat , outPut)
outPut
}
catch ( e : Exception){
e.printStackTrace()
this
}
}
To use distance from I write another extension function
fun org.opencv.core.Point.distanceFrom(srcPoint: org.opencv.core.Point):
Double {
val w1 = this.x - srcPoint.x
val h1 = this.y - srcPoint.y
val distance = w1.pow(2) + h1.pow(2)
return sqrt(distance)
}
Also in this answer the correct src Points indices are :
0 : topleft
1 : topRight
2 : bottomLeft
3 : bottomRight
Good luck

not detecting filled circle, showing empty circle instead- Opencv

I am new to OpenCV and trying to make omr scanner from scratch and have snippet which is supposed to detect filled circles but it is doing quite opposite and detecting unfilled circle. Please show me my mistake in the code.
public void showFilledCircles(Bitmap paramView)
{
paramView = BitmapFactory.decodeFile(filename);
Mat localMat1 = new Mat();
Utils.bitmapToMat(paramView, localMat1);
Object localObject1 = new Mat();
double[] lo;
Imgproc.GaussianBlur(localMat1, (Mat)localObject1, new Size(3.0D, 3.0D), 3.0D, 2.5D);
Mat localMat2 = new Mat();
Imgproc.cvtColor((Mat)localObject1, localMat2, 7);
localObject1 = new ArrayList();
Object localObject2 = new Mat();
Mat localMat3 = new Mat();
Imgproc.Canny(localMat2, localMat3, 140.0D, 255.0D);
Imgproc.findContours(localMat3, (List)localObject1, (Mat)localObject2,1,2);
int i = 0;
while (i < ((List)localObject1).size())
{
Imgproc.drawContours(localMat2, (List)localObject1, i, new Scalar(0.0D, 0.0D, 255.0D), 2);
//Log.i("Local Objects","Local Object Point -------------------"+localMat2);
i += 1;
}
localObject1 = new Mat();
Core.inRange(localMat2, new Scalar(70.0D, 70.0D, 70.0D), new Scalar(255.0D, 255.0D, 255.0D), (Mat)localObject1);
localMat2 = localMat1.clone();
Imgproc.HoughCircles((Mat)localObject1, localMat2, 3, 1.0D, 20.0D, 40.0D, 10.0D, 6, 18);
i = 0;
for (;;)
{
if (i < localMat2.cols())
{
localObject1 = localMat2.get(0, i);
lo = localMat2.get(0, i);
if (localObject1 != null) {}
}
else
{
Utils.matToBitmap(localMat1, paramView);
this.imageView.setImageBitmap(paramView);
//this.imageView.setRotation(90.0F);
return;
}
localObject2 = new Point(Math.round(lo[0]), Math.round(lo[1]));
int j = (int)Math.round(lo[2]);
Log.i("cicle Points ---------", localObject2 + " radius " + j);
Imgproc.circle(localMat1, (Point)localObject2, 1, new Scalar(0.0D, 0.0D, 255.0D), 5);
Imgproc.circle(localMat1, (Point)localObject2, j, new Scalar(255.0D, 0.0D, 0.0D), 5);
i += 1;
}
}
output image
for more precise detection of filled circle.
step 1: detect contours on image
step 2: create rectangle around detected contours.
step 3: depending on rectangle height and width choose only those contours which you want.
for filled circle detection refer to this question
Detect filled circle using opencv4Android

Opencv - select rectangle and apply transformation from image in android?

I want to detect paper sheet from image.I applied median Blur, Canny ,dilate,threshold,Etc. algorithms to find.i am able to find sheet but don't know how to crop rectangle and apply transformation
This is my code :-
Mat blurred = new Mat();
Imgproc.medianBlur(src, blurred, 9);
// Set up images to use.
Mat gray0 = new Mat(blurred.size(), CvType.CV_8U);
Mat gray = new Mat();
// For Core.mixChannels.
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
List<MatOfPoint2f> rectangles = new ArrayList<MatOfPoint2f>();
List<Mat> sources = new ArrayList<Mat>();
sources.add(blurred);
List<Mat> destinations = new ArrayList<Mat>();
destinations.add(gray0);
// To filter rectangles by their areas.
int srcArea = src.rows() * src.cols();
// Find squares in every color plane of the image.
for (int c = 0; c < 3; c++) {
int[] ch = {c, 0};
MatOfInt fromTo = new MatOfInt(ch);
Core.mixChannels(sources, destinations, fromTo);
// Try several threshold levels.
for (int l = 0; l < N; l++) {
if (l == 0) {
// HACK: Use Canny instead of zero threshold level.
// Canny helps to catch squares with gradient shading.
// NOTE: No kernel size parameters on Java API.
Imgproc.Canny(gray0, gray, 0, CANNY_THRESHOLD);
// Dilate Canny output to remove potential holes between edge segments.
Imgproc.dilate(gray, gray, Mat.ones(new Size(3, 3), 0));
} else {
int threshold = (l + 1) * 255 / N;
Imgproc.threshold(gray0, gray, threshold, 255, Imgproc.THRESH_BINARY);
}
// Find contours and store them all as a list.
Imgproc.findContours(gray, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
int i=0;
for (MatOfPoint contour : contours) {
MatOfPoint2f contourFloat = GeomUtils.toMatOfPointFloat(contour);
double arcLen = Imgproc.arcLength(contourFloat, true) * 0.02;
// Approximate polygonal curves.
MatOfPoint2f approx = new MatOfPoint2f();
Imgproc.approxPolyDP(contourFloat, approx, arcLen, true);
if (isRectangle(approx, srcArea)) {
Imgproc.drawContours(src, contours, i, new Scalar(255, 0, 0), 3);
//rectangles.add(approx);
/*Rect rect = Imgproc.boundingRect(contour);
Log.e("Rectangle Finder:-" + i, "Height:-" + rect.height + ", Width:-" + rect.width + " and Area:-" + rect.area() + "\nX:-" + rect.x + ",Y:-" + rect.y);*/
}
i++;
}
}
I want to select only white papersheet.please help me
Thanks in advance

Why is pointPolygonTest() method of OpenCV4Android returning -1 for every pixel?

In the following code, I have carried out the following steps:
Loaded an image from sdcard.
Converted it to HSV format.
Used inRange function to mask out the red color.
Used findContours to find the contours.
Find the largest contour from those contours.
Created an ROI around the largest contour using boundingRect and submat functions.
Converted this ROI Mat to HSV format.
Iterated through the ROI Mat, and check for each pixel if it lies within the largest contour. I used the method pointPolygonTest to find this out, but it returns -1 for every pixel, as can be seen from the Log.i output I have pasted here. The question is why? How can I correct this.
private Scalar detectColoredBlob() {
rgbaFrame = Highgui.imread("/mnt/sdcard/DCIM/rgbaMat4Mask.bmp");
Mat hsvImage = new Mat();
Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_BGR2HSV);
Highgui.imwrite("/mnt/sdcard/DCIM/hsvImage.bmp", hsvImage);// check
Mat maskedImage = new Mat();
Core.inRange(hsvImage, new Scalar(0, 100, 100), new Scalar(10, 255, 255), maskedImage);
Highgui.imwrite("/mnt/sdcard/DCIM/maskedImage.bmp", maskedImage);// check
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(maskedImage, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
// \/ We will use only the largest contour. Other contours (any other possible blobs of this color range) will be ignored.
MatOfPoint largestContour = contours.get(0);
double largestContourArea = Imgproc.contourArea(largestContour);
for (int i = 1; i < contours.size(); ++i) {// NB Notice the prefix increment.
MatOfPoint currentContour = contours.get(i);
double currentContourArea = Imgproc.contourArea(currentContour);
if (currentContourArea > largestContourArea) {
largestContourArea = currentContourArea;
largestContour = currentContour;
}
}
MatOfPoint2f largestContour2f = new MatOfPoint2f(largestContour.toArray());// Required on Line 289. See http://stackoverflow.com/questions/11273588/how-to-convert-matofpoint-to-matofpoint2f-in-opencv-java-api
Rect detectedBlobRoi = Imgproc.boundingRect(largestContour);
Mat detectedBlobRgba = rgbaFrame.submat(detectedBlobRoi);
Highgui.imwrite("/mnt/sdcard/DCIM/detectedBlobRgba.bmp", detectedBlobRgba);// check
Mat detectedBlobHsv = new Mat();
Imgproc.cvtColor(detectedBlobRgba, detectedBlobHsv, Imgproc.COLOR_BGR2HSV);
Highgui.imwrite("/mnt/sdcard/DCIM/roiHsv.bmp", detectedBlobHsv);// check
for (int firstCoordinate = 0; firstCoordinate < detectedBlobHsv.rows(); firstCoordinate++) {
for (int secondCoordinate = 0; secondCoordinate < detectedBlobHsv.cols(); secondCoordinate++) {
Log.i(TAG, "HAPPY " + Arrays.toString(detectedBlobHsv.get(firstCoordinate, secondCoordinate)));
if (Imgproc.pointPolygonTest(largestContour2f, new Point(firstCoordinate, secondCoordinate), false) == -1) {
Log.i(TAG, "HAPPY ....................... OUTSIDE");
}
}
}
Highgui.imwrite("/mnt/sdcard/DCIM/processedcontoured.bmp", detectedBlobHsv);// check
EDIT:
I am doing this because I need to compute the average HSV color of pixels lying inside the contour (i.e. the average HSV color of the biggest red colored blob). If I computed the average color of the ROI detectedBlobHsv by the normal formula, I would do something like
Scalar averageHsvColor= new Scalar(256);
Scalar sumHsvOfPixels = new Scalar(256);
sumHsvOfPixels = Core.sumElems(detectedBlobHsv);
int numOfPixels = detectedBlobHsv.width() * detectedBlobHsv.height();
for (int channel=0; channel<sumHsvOfPixels.val.length; channel++) {
averageHsvColor = sumHsvOfPixels.val[channel]/numOfPixels;
}
So somebody here on SO (probably you?) had suggested me a way to exclude pixels outside my contour a while back. I'd implement that like:
//Giving pixels outside contour of interest an HSV value of `double[]{0,0,0}`, so that they don't affect the computation of `sumHsvOfPixels` while computing average,
//and while keeping track of the number of pixels removed from computation this way, so we can subtract that number from the `$numOfPixels` during computation of average.
int pixelsRemoved = 0;
for (int row=0; row<detectedBlobHsv.rows(); row++) {
for (int col=0; col<detectedBlobHsv.cols(); col++) {
if (Imgproc.pointPolygonTest(largestContour2f, new Point(row, col), false) == -1) {
detectedBlobHsv.put(row, col, new double[]{0,0,0});
pixelsRemoved++;
}
}
}
Then compute the average like
Scalar averageHsvColor= new Scalar(256);
Scalar sumHsvOfPixels = new Scalar(256);
sumHsvOfPixels = Core.sumElems(detectedBlobHsv); //This will now exclude pixels outside the contour
int numOfPixels = ( detectedBlobHsv.width()*detectedBlobHsv.height() )-pixelsRemoved;
for (int channel=0; channel<sumHsvOfPixels.val.length; channel++) {
averageHsvColor = sumHsvOfPixels.val[channel]/numOfPixels;
}
EDIT 1:
Towards the end of the following method, I have created the mask with a list of MatOfPoints which contains the largest contour only. When I wrote it to SDCard, I got
I don't know where I messed up!
private Scalar detectColoredBlob() {
//Highgui.imwrite("/mnt/sdcard/DCIM/rgbaFrame.jpg", rgbaFrame);// check
rgbaFrame = Highgui.imread("/mnt/sdcard/DCIM/rgbaMat4Mask.bmp");
//GIVING A UNIFORM VALUE OF 255 TO THE V CHANNEL OF EACH PIXEL (255 IS THE MAXIMUM VALUE OF V ALLOWED - Simulating a maximum light condition)
for (int firstCoordinate = 0; firstCoordinate < rgbaFrame.rows(); firstCoordinate++) {
for (int secondCoordinate = 0; secondCoordinate < rgbaFrame.cols(); secondCoordinate++) {
double[] pixelChannels = rgbaFrame.get(firstCoordinate, secondCoordinate);
pixelChannels[2] = 255;
rgbaFrame.put(firstCoordinate, secondCoordinate, pixelChannels);
}
}
Mat hsvImage = new Mat();
Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_BGR2HSV);
Highgui.imwrite("/mnt/sdcard/DCIM/hsvImage.bmp", hsvImage);// check
Mat maskedImage = new Mat();
Core.inRange(hsvImage, new Scalar(0, 100, 100), new Scalar(10, 255, 255), maskedImage);
Highgui.imwrite("/mnt/sdcard/DCIM/maskedImage.bmp", maskedImage);// check
// Mat dilatedMat = new Mat();
// Imgproc.dilate(maskedImage, dilatedMat, new Mat());
// Highgui.imwrite("/mnt/sdcard/DCIM/dilatedMat.jpg", dilatedMat);// check
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(maskedImage, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
//FINDING THE BIGGEST CONTOUR
// \/ We will use only the largest contour. Other contours (any other possible blobs of this color range) will be ignored.
MatOfPoint largestContour = contours.get(0);
double largestContourArea = Imgproc.contourArea(largestContour);
for (int i = 1; i < contours.size(); ++i) {// NB Notice the prefix increment.
MatOfPoint currentContour = contours.get(i);
double currentContourArea = Imgproc.contourArea(currentContour);
if (currentContourArea > largestContourArea) {
largestContourArea = currentContourArea;
largestContour = currentContour;
}
}
Rect detectedBlobRoi = Imgproc.boundingRect(largestContour);
Mat detectedBlobRgba = rgbaFrame.submat(detectedBlobRoi);
Highgui.imwrite("/mnt/sdcard/DCIM/detectedBlobRgba.bmp", detectedBlobRgba);// check
Mat detectedBlobHsv = new Mat();
Imgproc.cvtColor(detectedBlobRgba, detectedBlobHsv, Imgproc.COLOR_BGR2HSV);
Highgui.imwrite("/mnt/sdcard/DCIM/roiHsv.bmp", detectedBlobHsv);// check
List<MatOfPoint> largestContourList = new ArrayList<>();
largestContourList.add(largestContour);
Mat roiWithMask = new Mat(detectedBlobHsv.rows(), detectedBlobHsv.cols(), CvType.CV_8UC3);
roiWithMask.setTo(new Scalar(0,0,0));
Imgproc.drawContours(roiWithMask, largestContourList, 0, new Scalar(0, 255, 255), -1);//TODO Using -1 instead of CV_FILLED.
Highgui.imwrite("/mnt/sdcard/DCIM/roiWithMask.bmp", roiWithMask);// check
// CALCULATING THE AVERAGE COLOR OF THE DETECTED BLOB
// STEP 1:
double [] averageHsvColor = new double[]{0,0,0};
int numOfPixels = 0;
for (int firstCoordinate = 0; firstCoordinate < detectedBlobHsv.rows(); ++firstCoordinate) {
for (int secondCoordinate = 0; secondCoordinate < detectedBlobHsv.cols(); ++secondCoordinate) {
double hue = roiWithMask.get(firstCoordinate, secondCoordinate)[0];
double saturation = roiWithMask.get(firstCoordinate, secondCoordinate)[1];
double value = roiWithMask.get(firstCoordinate, secondCoordinate)[2];
averageHsvColor[0] += hue;
averageHsvColor[1] += saturation;
averageHsvColor[2] += value;
numOfPixels++;
}
}
averageHsvColor[0] /= numOfPixels;
averageHsvColor[1] /= numOfPixels;
averageHsvColor[1] /= numOfPixels;
return new Scalar(averageHsvColor);
}
EDIT 2:
I corrected my 3 channel mask and made a single channel mask
Mat roiMask = new Mat(rgbaFrame.rows(), rgbaFrame.cols(), CvType.CV_8UC1);
roiMask.setTo(new Scalar(0));
Imgproc.drawContours(roiMask, largestContourList, 0, new Scalar(255), -1);
and this resulted in the correct roiMask:
Then, before the comment // CALCULATING THE AVERAGE COLOR OF THE DETECTED BLOB, I added:
Mat newImageWithRoi = new Mat(rgbaFrame.rows(), rgbaFrame.cols(), CvType.CV_8UC3);
newImageWithRoi.setTo(new Scalar(0, 0, 0));
rgbaFrame.copyTo(newImageWithRoi, roiMask);
Highgui.imwrite("/mnt/sdcard/DCIM/newImageWithRoi.bmp", newImageWithRoi);//check
This resulted in:
Now again I don't know how to proceed. :s
You don't need to use pointPolygonTest, because you already have the mask.
You can simply sum up the values that lies on the mask. Something along the lines of (not able to test this):
// Initialize at 0!!!
Scalar averageHsvColor= new Scalar(0,0,0);
int numOfPixels = 0;
for(int r=0; r<detectedBlobHsv.height(); ++r)
{
for(int c=0; c<detectedBlobHsv.width(); ++c)
{
if( /* value of mask(r,c) > 0 */)
{
int H = // get H value of pixel at (r, c)
int S = // get S value of pixel at (r, c)
int V = // get V value of pixel at (r, c)
// Sum values
averageHsvColor[0] += H;
averageHsvColor[1] += S;
averageHsvColor[2] += V;
// Increment number of pixels inside mask
numOfPixels ++;
}
}
}
// Compute average
averageHsvColor[0] /= numOfPixels ;
averageHsvColor[1] /= numOfPixels ;
averageHsvColor[2] /= numOfPixels ;

not able tot detect phisycal door or other big rectangle in open cv android

I wrote code to detect rectangles in open cv. And i am able to detect few object but i am not able to detect physical door or big rectangle. Please check my code and correct me if i am wrong somewhere . Another problem is this code is not able to detect rectangle constantly so when i draw rectangle it comes and go , comes and go and it looks bad. Any way to detect regularly in every frame.
Mat output= getGray(inputFrame.rgba(),inputFrame.rgba());
Imgproc.medianBlur(output, output, 5);
Imgproc.erode(output, output, new Mat());
Imgproc.dilate(output, output, new Mat());
Mat edges = new Mat();
Imgproc.Canny(output, output, 5, 50);
// Vector<MatOfPoint> vector=new Vector<MatOfPoint>();
// Imgproc.findContours(output, points, output, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
contours.clear();
Imgproc.findContours(output, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
MatOfPoint2f approxCurve = new MatOfPoint2f();
rgbImage=inputFrame.rgba();
mDrawnContours.clear();
> Blockquote
for(int i=0;i< contours.size();i++){
MatOfPoint tempContour=contours.get(i);
MatOfPoint2f newMat = new MatOfPoint2f( tempContour.toArray() );
int contourSize = (int)tempContour.total();
Imgproc.approxPolyDP(newMat, approxCurve, contourSize*0.15, true);
MatOfPoint points=new MatOfPoint(approxCurve.toArray());
if((Math.abs(Imgproc.contourArea(tempContour))<100) || !Imgproc.isContourConvex(points)){
Log.i(TAG, "::onCameraFrame:" + " too small");
appendLog("Too small");
continue;
}
else if(points.toArray().length >= 4 && points.toArray().length <= 6){
int vtc = points.toArray().length;
Vector<Double> cosList=new Vector<Double>();
for (int j = 2; j < vtc+1; j++){
cosList.add(angle(points.toArray()[j%vtc], points.toArray()[j-2], points.toArray()[j-1]));
}
double mincos = getMin(cosList);
double maxcos = getMax(cosList);
Log.i(TAG, "::onCameraFrame:" + "mincos:"+mincos+"maxcos:"+maxcos);
if (vtc == 4 && mincos >= -0.1 && maxcos <= 0.3)
{
mTotalSquare++;
Imgproc.drawContours(rgbImage, contours, i, new Scalar(0,0,255));
DrawnContours contours2=new DrawnContours();
contours2.setIndex(i);
mDrawnContours.add(contours2);
Log.i(TAG, "::onCameraFrame:" + "found");
appendLog("found");
}
else{
Log.i(TAG, "::onCameraFrame:" +" not found " +"mincos:"+mincos+"maxcos:"+maxcos);
appendLog("not found 1");
}
}
return rgbImage
Let me know if you have any questions.
I suppose, that large contours have more than 4 edges. Their contour consists of large number of short line segments (depends on approximation function parameter in line
Imgproc.approxPolyDP(newMat, approxCurve, contourSize*0.15, true);
).
And you have condition which check for edge numbers:
points.toArray().length <= 6

Categories

Resources