Opencv 查找轮廓
Opencv findContour
我正在做一个检测伤口的项目,伤口的类型如下所附的名称(原件)。
我曾尝试使用以下方法来检测感兴趣的伤口区域。但是,检测结果并不是我想要达到的结果(见附件 named(outputFromAboveMethod))。我希望实现的最终结果在附件中 named(WhatIWant)
谁能帮帮我。
当前方法的代码:
public class DetectTask extends AsyncTask<Integer, Bitmap, Bitmap> {
@Override
protected void onPreExecute() {
super.onPreExecute();
dlg.setMessage("Processing");
dlg.show();
}
@Override
protected Bitmap doInBackground(Integer... params) {
Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC3);
Utils.bitmapToMat(bitmap, mat);
Mat rgbMat = new Mat();
Imgproc.cvtColor(mat, rgbMat, Imgproc.COLOR_RGBA2BGR);
Mat dilatedMat = new Mat();
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(7, 7));
Imgproc.morphologyEx(rgbMat, dilatedMat, Imgproc.MORPH_OPEN, kernel);
//red
Mat redMat = new Mat();
Core.inRange(rgbMat, new Scalar(0, 0, 120), new Scalar(100, 100, 255), redMat);
//find contour
Mat hierarchy = new Mat();
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(redMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
double largest_area =0;
int largest_contour_index = 0;
for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
double contourArea = Imgproc.contourArea(contours.get(contourIdx));
if (contourArea > largest_area) {
largest_area = contourArea;
largest_contour_index = contourIdx;
}
}
Imgproc.drawContours(mat, contours, largest_contour_index, new Scalar(0, 255, 0, 255), 3);
Bitmap outputImage= Bitmap.createBitmap(mat.cols(), mat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mat, outputImage);
return outputImage;
}
@Override
protected void onPostExecute(final Bitmap outputImage) {
imageview.setImageBitmap(outputImage);
dlg.dismiss();
}
}
originalImage
outputFromAboveMethod
WhatIWant
afterConvextHull
更改代码以绘制找到的轮廓的凸包几乎可以满足您的需求。凸包是轮廓的'outline'。例子:
此代码获取 findContours() 的输出并创建一个凸包列表。
List<MatOfPoint> hullList = new ArrayList<>();
for (MatOfPoint contour : contours) {
MatOfInt hull = new MatOfInt();
Imgproc.convexHull(contour, hull);
Point[] contourArray = contour.toArray();
Point[] hullPoints = new Point[hull.rows()];
List<Integer> hullContourIdxList = hull.toList();
for (int i = 0; i < hullContourIdxList.size(); i++) {
hullPoints[i] = contourArray[hullContourIdxList.get(i)];
}
hullList.add(new MatOfPoint(hullPoints));
}
你可以画一个凸包
Imgproc.drawContours(drawing, hullList, index, color );
检查这个 tutorial,它包含一个工作示例。
我正在做一个检测伤口的项目,伤口的类型如下所附的名称(原件)。
我曾尝试使用以下方法来检测感兴趣的伤口区域。但是,检测结果并不是我想要达到的结果(见附件 named(outputFromAboveMethod))。我希望实现的最终结果在附件中 named(WhatIWant)
谁能帮帮我。
当前方法的代码:
public class DetectTask extends AsyncTask<Integer, Bitmap, Bitmap> {
@Override
protected void onPreExecute() {
super.onPreExecute();
dlg.setMessage("Processing");
dlg.show();
}
@Override
protected Bitmap doInBackground(Integer... params) {
Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC3);
Utils.bitmapToMat(bitmap, mat);
Mat rgbMat = new Mat();
Imgproc.cvtColor(mat, rgbMat, Imgproc.COLOR_RGBA2BGR);
Mat dilatedMat = new Mat();
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(7, 7));
Imgproc.morphologyEx(rgbMat, dilatedMat, Imgproc.MORPH_OPEN, kernel);
//red
Mat redMat = new Mat();
Core.inRange(rgbMat, new Scalar(0, 0, 120), new Scalar(100, 100, 255), redMat);
//find contour
Mat hierarchy = new Mat();
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(redMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
double largest_area =0;
int largest_contour_index = 0;
for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
double contourArea = Imgproc.contourArea(contours.get(contourIdx));
if (contourArea > largest_area) {
largest_area = contourArea;
largest_contour_index = contourIdx;
}
}
Imgproc.drawContours(mat, contours, largest_contour_index, new Scalar(0, 255, 0, 255), 3);
Bitmap outputImage= Bitmap.createBitmap(mat.cols(), mat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mat, outputImage);
return outputImage;
}
@Override
protected void onPostExecute(final Bitmap outputImage) {
imageview.setImageBitmap(outputImage);
dlg.dismiss();
}
}
originalImage
outputFromAboveMethod
WhatIWant
afterConvextHull
更改代码以绘制找到的轮廓的凸包几乎可以满足您的需求。凸包是轮廓的'outline'。例子:
此代码获取 findContours() 的输出并创建一个凸包列表。
List<MatOfPoint> hullList = new ArrayList<>();
for (MatOfPoint contour : contours) {
MatOfInt hull = new MatOfInt();
Imgproc.convexHull(contour, hull);
Point[] contourArray = contour.toArray();
Point[] hullPoints = new Point[hull.rows()];
List<Integer> hullContourIdxList = hull.toList();
for (int i = 0; i < hullContourIdxList.size(); i++) {
hullPoints[i] = contourArray[hullContourIdxList.get(i)];
}
hullList.add(new MatOfPoint(hullPoints));
}
你可以画一个凸包
Imgproc.drawContours(drawing, hullList, index, color );
检查这个 tutorial,它包含一个工作示例。