Reputation: 449
I am trying to detect a certain area(rectangle) in an image, and get its upper and lower bounds, but im stuck at the point where i have to get the Region of interest.
Starting from this image:
I want to get the area of interest like so:
I converted the python code answered by Alexander Reynolds here, But i cant seem to view the result as I'm getting an error:
java.lang.IllegalArgumentException: bmp == null
at
Utils.matToBitmap(roiMat,temp);
bitmap = constructor.getBmp();
Mat srcMat = new Mat();
Utils.bitmapToMat(bitmap, srcMat);
Mat hsvMat = new Mat();
Imgproc.cvtColor(srcMat,hsvMat,Imgproc.COLOR_BGR2HSV);
Mat roiMat;
Range rowRange = new Range(95, 436); //95 837, top left// 436,837 top right,,//95 895,, btm left, //436, 895 btm right
Range colRange = new Range(837, 895);
roiMat = new Mat(hsvMat, colRange, rowRange); // public Mat(Mat m, Range rowRange, Range colRange)
Utils.matToBitmap(roiMat, temp);
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap(temp);
}
Upvotes: 2
Views: 3445
Reputation: 13343
You can try call this method:
private Bitmap findRoi(Bitmap sourceBitmap) {
Bitmap roiBitmap = null;
Scalar green = new Scalar(0, 255, 0, 255);
Mat sourceMat = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3);
Utils.bitmapToMat(sourceBitmap, sourceMat);
Mat roiTmp = sourceMat.clone();
final Mat hsvMat = new Mat();
sourceMat.copyTo(hsvMat);
// convert mat to HSV format for Core.inRange()
Imgproc.cvtColor(hsvMat, hsvMat, Imgproc.COLOR_RGB2HSV);
Scalar lowerb = new Scalar(85, 50, 40); // lower color border for BLUE
Scalar upperb = new Scalar(135, 255, 255); // upper color border for BLUE
Core.inRange(hsvMat, lowerb, upperb, roiTmp); // select only blue pixels
// find contours
List<MatOfPoint> contours = new ArrayList<>();
List<RotatedRect> boundingRects = new ArrayList<>();
Imgproc.findContours(roiTmp, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
// find appropriate bounding rectangles
for (MatOfPoint contour : contours) {
MatOfPoint2f areaPoints = new MatOfPoint2f(contour.toArray());
RotatedRect boundingRect = Imgproc.minAreaRect(areaPoints);
double rectangleArea = boundingRect.size.area();
// test min ROI area in pixels
if (rectangleArea > 400) {
Point rotated_rect_points[] = new Point[4];
boundingRect.points(rotated_rect_points);
Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));
// test horizontal ROI orientation
if (rect.width > rect.height) {
Imgproc.rectangle(sourceMat, rect.tl(), rect.br(), green, 3);
}
}
}
roiBitmap = Bitmap.createBitmap(sourceMat.cols(), sourceMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(sourceMat, roiBitmap);
return roiBitmap;
}
from, for example, button click:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "OpenCVLoader.initDebug() - ERROR");
} else {
Log.d(TAG, "OpenCVLoader.initDebug() - OK");
}
mImageView = (ImageView) findViewById(R.id.source_image_view);
mProcessButton = (Button) findViewById(R.id.process_button);
mProcessButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bitmap bmSource = BitmapFactory.decodeResource(getResources(), R.drawable.test);
Bitmap bmRoi = findRoi(bmSource);
mImageView.setImageBitmap(bmRoi);
}
});
}
when activity_main.xml
is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.test.opencv.opencvstackoverflow.MainActivity">
<ImageView
android:id="@+id/source_image_view"
android:layout_above="@+id/process_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
app:srcCompat="@drawable/test"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
/>
<Button
android:id="@+id/process_button"
android:text="Find ROI"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
and you'll got something like that as result:
NB! Maybe You should adjust Scalar
lowerb
and upperb
according to Your condition as described (as You know) by Alexander Reynolds here:
This ROI contains only blue pixels, so I can find the mean blue value, and the standard deviation of the blue values to use as the values for inRange().
mu, sig = cv2.meanStdDev(roi) a = 9 blue_mask = cv2.inRange(hsv, mu-a*sig, mu+a*sig)
Also 400
in if (rectangleArea > 400)
may needs to be adjusted according minimal area of ROI.
Upvotes: 2