我正在尝试检测图像中的某个区域(矩形),并获得其上限和下限,但即时卡在我必须获得感兴趣区域的位置。
从这张图片开始:
我想像这样得到感兴趣的领域:
我转换了Alexander Reynolds here回答的python代码, 但我似乎无法查看结果,因为我收到了错误:
java.lang.IllegalArgumentException:bmp == null
在
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);
}
答案 0 :(得分:3)
您可以尝试调用此方法:
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;
}
来自,例如,按钮点击:
@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);
}
});
}
activity_main.xml
时:
<?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>
你将得到类似的东西:
NB!也许您应该根据Alexander Reynolds here所述的条件(如您所知)调整Scalar
lowerb
和upperb
:
此ROI仅包含蓝色像素,因此我可以找到平均蓝色值, 以及用作值的蓝色值的标准偏差 INRANGE()。
mu, sig = cv2.meanStdDev(roi) a = 9 blue_mask = cv2.inRange(hsv, mu-a*sig, mu+a*sig)
400
中的if (rectangleArea > 400)
也可能需要根据投资回报率的最小区域进行调整。