问题
I am new to OpenCV and trying to learn by implementing. I need to draw the contours I have detected in new Mat so I can work with them.
This is my Original image:

After doing some work I achieved this by finding and drawing contours:

Here's my code
m = Utils.loadResource(MainActivity.this, R.drawable.sheet1, Highgui.CV_LOAD_IMAGE_COLOR);
Bitmap bm = Bitmap.createBitmap(m.cols(), m.rows(),Bitmap.Config.ARGB_8888);
Imgproc.cvtColor(m, m, Imgproc.COLOR_BGR2GRAY);
Imgproc.medianBlur(m, m, 3);
Imgproc.threshold(m, m, 0, 255, Imgproc.THRESH_OTSU);
Core.bitwise_not(m, m);
Imgproc.dilate(m, m, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1,118)));
//Contours detection
java.util.List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(m, contours, new Mat() ,Imgproc.RETR_EXTERNAL , Imgproc.CHAIN_APPROX_SIMPLE);
Imgproc.cvtColor(m, m, Imgproc.COLOR_GRAY2BGR);
//Contour drawing
Mat matArray = new Mat();
Imgproc.drawContours(m, contours, -1, new Scalar(153,255,204), 3);
Utils.matToBitmap(m, bm);
ImageView iv = (ImageView) findViewById(R.id.imageView1);
iv.setImageBitmap(bm);
Now, I want to save every MCQ in new Mat. How can this be implemented in android Java?
回答1:
You can use boundingRect
to have rectangular contours.
Then, for each contour, you can use the Point stored in it to create the new Mat. You can use cv::getPerspectiveTransform
and cv::warpPerspective
with the points and an empty Mat.
I don't know how it works in Java, but in C++ its something similar to that.
you can take a look at this : http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.html
Hope it helps.
回答2:
Here is the code you can change the inRange values as per your requirement:
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
/* orientation change added by Susmita
Mat mRgbaT = mRGBa.t();
Core.flip(mRGBa.t(), mRgbaT, 1);
Imgproc.resize(mRgbaT, mRgbaT, mRGBa.size());
return mRgbaT;*/
//
//Get a frame from the camera in RGB format
mRGBa = inputFrame.rgba();
//Remove noise from the image.
Imgproc.medianBlur(mRGBa, mBlur, 5);
//Convert image to HSV format
Imgproc.cvtColor(mBlur, imHSV, Imgproc.COLOR_RGB2HSV);
//Filter out Green coloured objects in the image.
//TODO: This scale has to be optimized to detect on Greed colored LED
Core.inRange(imHSV, new Scalar(50, 100, 100, 100), new Scalar(70, 225, 255, 255), imHSV);
//Remove noise from the image.
Imgproc.GaussianBlur(imHSV, imHSV, new Size(9, 9), 2, 2);
//Convert the image from HSV to Gray scale image.
imHSV.convertTo(imGray, CvType.CV_8U);
//Apply threshold to the gray scale image to remove unnecessay objects from image.
Imgproc.threshold(imGray, imGray, 50, 255, Imgproc.THRESH_BINARY);
//Perform edge detection the image
Imgproc.Canny(imGray, imGray, 100, 200);
//Find Contours(closed shapes) in the image. (Detected LED will be a contour)
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(imGray, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));
// For each detected contour(closed shape) Find the co-ordinates of the countour and draw a rectangle on the input image.
//TODO: For each Contour detected, below logic can be changed to detect countours having only 4 edges(rectangle/square).
for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
// Minimum size allowed for consideration
MatOfPoint2f approxCurve = new MatOfPoint2f();
MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(contourIdx).toArray());
//Processing on mMOP2f1 which is in type MatOfPoint2f
double approxDistance = Imgproc.arcLength(contour2f, true) * 0.02;
//Detect contours
Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);
//Convert back to MatOfPoint
MatOfPoint points = new MatOfPoint(approxCurve.toArray());
// Get bounding rect of contour
Rect rect = Imgproc.boundingRect(points);
//Draw rectangle for the detected countour on the original image
Imgproc.rectangle(mRGBa, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(255, 0, 255, 255), 2);
}
return mRGBa;
}
来源:https://stackoverflow.com/questions/29184697/opencv-android-copy-part-of-an-image-to-new-mat