我想检测黑色物体下方的整个区域。
我已经成功地获得了黑色物体下方的矩形区域,如下所示
Point leftPoint = new Point(0,yValueBlack); //far left, black object height
Point rightPoint = new Point(sourceBitmap.getWidth(),sourceBitmap.getHeight()); //btm right of entire bitmap
Rect bottomRect = new Rect(leftPoint,rightPoint);
由此Rect bottomRect = new Rect(leftPoint,rightPoint);
是我想要检测绿色 strip 的区域,如图所示。这是为了防止应用程序搜索图片上方的任何内容并在其他对象位于框架中时导致错误。
我有一个由边界矩形包围的黑色对象的位图,我只想检测 Rect bottomRect = new Rect(leftPoint,rightPoint);
从该位图中绘制绿色 strip 的边界矩形。
我定义垫子尺寸的方式是这样的
Mat sourceMat = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3);
但是,当我尝试使用相同的方法来定义我的垫子尺寸以适合黑色对象下方的矩形区域时,如下所示:
Mat croppedMat = new Mat(bottomRect, CvType.CV_8UC3);
它会给我一个错误。
这就是我认为的样子:
Detect and draw bounding rectangle around black object (Done)
Find rectangle area(RAT) below black object
Detect and draw bounding rectangle around green object within the RAT(I can detect and draw bounding rectangle for green object, cant seem to do it WITHIN the specified RAT)
Display bitmap like shown in image below(done)
编辑:
检测到黑色物体后,绘制边界矩形,当前位于 roiBitmap
。裁剪roiBitmap
并尝试在 imageview
中显示它(我将从最终裁剪掉的位图中检测到绿色胶带。)给我错误:
CvException [org.opencv.core.CvException: cv::Exception: /build/master_pack-android/opencv/modules/core/src/matrix.cpp:483: error: (-215) 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows in function cv::Mat::Mat(const cv::Mat&, const cv::Range&, const cv::Range&)
我的代码:
private Bitmap findCombine(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();
bitmapWidth = sourceBitmap.getWidth();
Log.e("bitmapWidth", String.valueOf(bitmapWidth));
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
Scalar lowerblack = new Scalar(0, 0, 0); // lower color border for BLACK
Scalar upperblack = new Scalar(180, 255, 40); // upper color border for BLACK
Scalar testRunL = new Scalar(60, 50, 40); // lower Green 83 100 51
Scalar testRunU = new Scalar(90, 255, 255); // upper Green
Core.inRange(hsvMat, lowerblack, upperblack, 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 > 1300 && rectangleArea < 500000) {//400000
Point rotated_rect_points[] = new Point[4];
boundingRect.points(rotated_rect_points);
Rect rect3 = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));
Log.e("blackArea", String.valueOf(rect3.area()));
// test horizontal ROI orientation
if (rect3.height > rect3.width) {
Imgproc.rectangle(sourceMat, rect3.tl(), rect3.br(), green, 3);
xBlack = rect3.br().x;
yBlack = rect3.br().y;//bottom
battHeight = (rect3.br().y - rect3.tl().y); //batt height in pixel
Log.e("BLACKBR, TL", String.valueOf(rect3.br().y) + "," + String.valueOf(rect3.tl().y));
}
}
}
roiBitmap = Bitmap.createBitmap(sourceMat.cols(), sourceMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(sourceMat, roiBitmap);
Point leftPoint = new Point(0, yBlack); //far left, black object height
Point rightPoint = new Point(roiBitmap.getWidth(), roiBitmap.getHeight()); //btm right of entire bitmap
Rect bottomRect = new Rect(leftPoint, rightPoint);
double rectWidth = sourceBitmap.getWidth() - 0;
double rectHeight = sourceBitmap.getHeight() - yBlack;
Log.e("rectWidth", String.valueOf(rectWidth));
Log.e("rectHeight", String.valueOf(rectHeight));
Size bottomRectSize = new Size(rectHeight, rectWidth);
Bitmap cropBitmap = null;
Bitmap sourceBitmapT = null;
Mat sourceMatT = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3);
Log.e("sourceMatT, BottomRect","SMT "+ String.valueOf(sourceMatT.size()) + " bottomRect " + String.valueOf(bottomRect.size()));
Mat cropMat = new Mat(sourceMatT, bottomRect);
ImageView imgCropped = (ImageView) findViewById(R.id.cropped_image_view);
Utils.bitmapToMat(roiBitmap, sourceMatT);
//mgCropped.setImageBitmap(sourceBitmapT);
Utils.matToBitmap(cropMat, cropBitmap);
imgCropped.setImageBitmap(cropBitmap);
Log.e("sourceMatT, BottomRect","SMT "+ String.valueOf(sourceMatT.size()) + " bottomRect " + String.valueOf(bottomRect.size()));
返回给我这些值:
sourceMatT, BottomRect: SMT 1920x1080 bottomRect 1080x656
最佳答案
您可以“提取”图像的一部分,然后在整个提取区域中查找轮廓,然后纠正查找轮廓的坐标。类似这样的事情:
提取sourceMat
的一部分:
// set top left position and dimensions of extracted area
int topLeftX = ...;
int topLeftY = ...;
int width = ...;
int height = ...;
// create Rect object for extracted area
Rect extractedRect = new Rect (topLeftX, topLeftY, width, height);
// create Mat from sourceMat
Mat extractedMat = new Mat(sourceMat, extractedRect);
在整个提取区域上查找轮廓/矩形或其他内容:
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(extractedMat, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
建立轮廓的正确坐标(添加到其X
和Y
坐标,相应的topLeftX
和topLeftY
用于正确放置在 sourceMat
上):
List<Rect> rectsOnSourcemat = new ArrayList<>();
for (MatOfPoint contour : contours) {
MatOfPoint2f contourPoints = new MatOfPoint2f(contour.toArray());
RotatedRect boundingRect = Imgproc.minAreaRect(areaPoints);
Point rotated_rect_points[] = new Point[4];
boundingRect.points(rotated_rect_points);
// correct coords here for sourceMat:
for (int ixPoint = 0; ixPoint < 4; ixPoint++) {
rotated_rect_points[ixPoint].x += topLeftX;
rotated_rect_points[ixPoint].y += topLeftY;
}
// crate bounding rect for sourceMat
Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));
rectsOnSourcemat.add(rect);
}
现在在 rectsOnSourcemat
变量中,您将获得基于提取的区域对象的矩形列表,但已经包含 sourceMat
的坐标。
关于java - OpenCV、安卓 : color detection from particular area or portion of an image?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45706489/