import org.opencv.core.*;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Handler;
public class Main {
private static final boolean LOG_MEM_USAGE = true;
/**
* detect only red objects
*/
private static final boolean DETECT_RED_OBJECTS_ONLY = false;
/**
* the lower red HSV range (lower limit)
*/
private static final Scalar HSV_LOW_RED1 = new Scalar(0, 100, 100);
/**
* the lower red HSV range (upper limit)
*/
private static final Scalar HSV_LOW_RED2 = new Scalar(10, 255, 255);
/**
* the upper red HSV range (lower limit)
*/
private static final Scalar HSV_HIGH_RED1 = new Scalar(160, 100, 100);
/**
* the upper red HSV range (upper limit)
*/
private static final Scalar HSV_HIGH_RED2 = new Scalar(179, 255, 255);
/**
* definition of RGB red
*/
private static final Scalar RGB_RED = new Scalar(255, 0, 0);
/**
* frame size width
*/
private static final int FRAME_SIZE_WIDTH = 640;
/**
* frame size height
*/
private static final int FRAME_SIZE_HEIGHT = 480;
/**
* whether or not to use a fixed frame size -> results usually in higher FPS
* 640 x 480
*/
private static final boolean FIXED_FRAME_SIZE = true;
/**
* whether or not to use the database to display
* an image on top of the camera
* when false the objects are labeled with writing
*/
private static final boolean DISPLAY_IMAGES = false;
/**
* image thresholded to black and white
*/
private Mat bw;
/**
* image converted to HSV
*/
private Mat hsv;
/**
* the image thresholded for the lower HSV red range
*/
private Mat lowerRedRange;
/**
* the image thresholded for the upper HSV red range
*/
private Mat upperRedRange;
/**
* the downscaled image (for removing noise)
*/
private Mat downscaled;
/**
* the upscaled image (for removing noise)
*/
private Mat upscaled;
/**
* the image changed by findContours
*/
private Mat contourImage;
/**
* the found contour as hierarchy vector
*/
private Mat hierarchyOutputVector;
/**
* approximated polygonal curve with specified precision
*/
private MatOfPoint2f approxCurve;
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.out.println("Hello Im OK");
Mat frame = Imgcodecs.imread("/home/chinthaka/Downloads/shape-detection-master/testimages/simpleshapes.png");
}
public Mat onCameraFrame(Mat inputFrame) {
// get the camera frame as gray scale image
Mat gray = null;
if (DETECT_RED_OBJECTS_ONLY) {
} else {
}
gray = inputFrame;
// the image to output on the screen in the end
// -> get the unchanged color image
Mat dst = inputFrame;
// down-scale and upscale the image to filter out the noise
Imgproc.pyrDown(gray, downscaled, new Size(gray.cols() / 2, gray.rows() / 2));
Imgproc.pyrUp(downscaled, upscaled, gray.size());
if (DETECT_RED_OBJECTS_ONLY) {
// convert the image from RGBA to HSV
Imgproc.cvtColor(upscaled, hsv, Imgproc.COLOR_RGB2HSV);
// threshold the image for the lower and upper HSV red range
Core.inRange(hsv, HSV_LOW_RED1, HSV_LOW_RED2, lowerRedRange);
Core.inRange(hsv, HSV_HIGH_RED1, HSV_HIGH_RED2, upperRedRange);
// put the two thresholded images together
Core.addWeighted(lowerRedRange, 1.0, upperRedRange, 1.0, 0.0, bw);
// apply canny to get edges only
Imgproc.Canny(bw, bw, 0, 255);
} else {
// Use Canny instead of threshold to catch squares with gradient shading
Imgproc.Canny(upscaled, bw, 0, 255);
}
// dilate canny output to remove potential
// holes between edge segments
Imgproc.dilate(bw, bw, new Mat(), new Point(-1, 1), 1);
// find contours and store them all as a list
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
contourImage = bw.clone();
Imgproc.findContours(
contourImage,
contours,
hierarchyOutputVector,
Imgproc.RETR_EXTERNAL,
Imgproc.CHAIN_APPROX_SIMPLE
);
// loop over all found contours
for (MatOfPoint cnt : contours) {
MatOfPoint2f curve = new MatOfPoint2f(cnt.toArray());
// approximates a polygonal curve with the specified precision
Imgproc.approxPolyDP(
curve,
approxCurve,
0.02 * Imgproc.arcLength(curve, true),
true
);
int numberVertices = (int) approxCurve.total();
double contourArea = Imgproc.contourArea(cnt);
// Log.d(TAG, "vertices:" + numberVertices);
// ignore to small areas
if (Math.abs(contourArea) < 100
// || !Imgproc.isContourConvex(
) {
continue;
}
// triangle detection
if (numberVertices == 3) {
if (DISPLAY_IMAGES) {
// doSomethingWithContent("triangle");
} else {
setLabel(dst, "TRI", cnt);
}
}
// rectangle, pentagon and hexagon detection
if (numberVertices >= 4 && numberVertices <= 6) {
List<Double> cos = new ArrayList<>();
for (int j = 2; j < numberVertices + 1; j++) {
cos.add(
angle(
approxCurve.toArray()[j % numberVertices],
approxCurve.toArray()[j - 2],
approxCurve.toArray()[j - 1]
)
);
}
Collections.sort(cos);
double mincos = cos.get(0);
double maxcos = cos.get(cos.size() - 1);
// rectangle detection
if (numberVertices == 4
&& mincos >= -0.1 && maxcos <= 0.3
) {
if (DISPLAY_IMAGES) {
// doSomethingWithContent("rectangle");
} else {
setLabel(dst, "RECT", cnt);
}
}
// pentagon detection
else if (numberVertices == 5
&& mincos >= -0.34 && maxcos <= -0.27) {
if (!DISPLAY_IMAGES) {
setLabel(dst, "PENTA", cnt);
}
}
// hexagon detection
else if (numberVertices == 6
&& mincos >= -0.55 && maxcos <= -0.45) {
if (!DISPLAY_IMAGES) {
setLabel(dst, "HEXA", cnt);
}
}
}
// circle detection
else {
Rect r = Imgproc.boundingRect(cnt);
int radius = r.width / 2;
if (Math.abs(
1 - (
r.width / r.height
)
) <= 0.2 &&
Math.abs(
1 - (
contourArea / (Math.PI * radius * radius)
)
) <= 0.2
) {
if (!DISPLAY_IMAGES) {
setLabel(dst, "CIR", cnt);
}
}
}
}
// return the matrix / image to show on the screen
return dst;
}
/**
* Helper function to find a cosine of angle between vectors
* from pt0->pt1 and pt0->pt2
*/
private static double angle(Point pt1, Point pt2, Point pt0)
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1 * dx2 + dy1 * dy2)
/ Math.sqrt(
(dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2) + 1e-10
);
}
/**
* display a label in the center of the given contur (in the given image)
* @param im the image to which the label is applied
* @param label the label / text to display
* @param contour the contour to which the label should apply
*/
private void setLabel(Mat im, String label, MatOfPoint contour) {
int fontface = Core.FONT_HERSHEY_SIMPLEX;
double scale = 3;//0.4;
int thickness = 3;//1;
int[] baseline = new int[1];
Size text = Imgproc.getTextSize(label, fontface, scale, thickness, baseline);
Rect r = Imgproc.boundingRect(contour);
Point pt = new Point(
r.x + ((r.width - text.width) / 2),
r.y + ((r.height + text.height) /2)
);
/*
Imgproc.rectangle(
im,
new Point(r.x + 0, r.y + baseline[0]),
new Point(r.x + text.width, r.y -text.height),
new Scalar(255,255,255),
-1
);
*/
Imgproc.putText(im, label, pt, fontface, scale, RGB_RED, thickness);
}
}
Input image : image
I have developed some code looking at another code but it has worked for android. I am using opencv with Java in intellij idea. How to identify shapes of this provided image. Could anyone please help me to build this code.