如何使用Android Opencv检测目标上的弹孔 [英] How to detect bullet holes on the target using Android Opencv
问题描述
我在一个项目中工作,我必须扫描目标并识别目标中的孔,并且必须根据镜头得分.我不知道确切的代码如何识别目标中的漏洞.我导入了opencv库,并通过了一个程序,如果我触摸它,它将识别出相应的颜色.现在,我被困在编码部分.这是给我的目标表的屏幕截图.
I am working in a project where I have to scan the target and recognize the holes in the target and have to score according to the shots. I am not aware of the exact code how to recognize the holes in the target. I imported the opencv library and gone through a program where if I touch it will recognize the corresponding color. Now I am stuck in the coding part. Here is the screenshot of the target sheet that is given to me.
任何人都可以帮助我进一步进行操作.预先感谢.
Could anyone please help me how to proceed further. Thanks in advance.
推荐答案
要做自己想做的事
1) find white areas with max brightness;
2) find bounding contours of areas with max brightness (from p.1);
3) find bounding boxes for contours from p.2;
4) count bounding boxes.
,并且还要考虑一些特殊情况,例如图像中的双孔".
and also take into account some special cases, like "twin" holes in your image.
要在Android上实现该步骤最简单的方法是使用 OpenCV .如何在此处中对其进行详细说明(您应该做一些工作:从此处并正确添加).然后,您应该看一些有关在Android中使用OpenCV的教程,例如,
To implement that steps on Android easiest way is to use OpenCV. How to add it to your project well described here (You should do some work to do to it: download SDK from here and add it correctly). Then You should take a look at some tutorial about using OpenCV in Android, for example, official. And than, You can use code like this (your image added to drawable
folder of demo project as target.png
):
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private ImageView mImageView;
private Button mProcessButton;
private Mat mSourceImageMat;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.target_image_view);
mProcessButton = (Button) findViewById(R.id.process_button);
mProcessButton.setVisibility(View.INVISIBLE);
mProcessButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
processImage();
}
});
}
private void processImage() {
try {
mSourceImageMat = Utils.loadResource(this, R.drawable.target);
Bitmap bm = Bitmap.createBitmap(mSourceImageMat.cols(), mSourceImageMat.rows(),Bitmap.Config.ARGB_8888);
final Mat mat = new Mat();
final List<Mat> channels = new ArrayList<>(3);
mSourceImageMat.copyTo(mat);
// split image channels: 0-H, 1-S, 2-V
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGB2HSV);
Core.split(mat, channels);
final Mat frameV = channels.get(2);
// find white areas with max brightness
Imgproc.threshold(frameV, frameV, 245, 255, Imgproc.THRESH_BINARY);
// find contours
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(frameV, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
// find average contour area for "twin" hole detection
double averageArea = 0;
int contoursCount = 0;
Iterator<MatOfPoint> each = contours.iterator();
while (each.hasNext()) {
averageArea += Imgproc.contourArea(each.next());
contoursCount++;
}
if (contoursCount != 0) {
averageArea /= contoursCount;
}
int holesCount = 0;
each = contours.iterator();
while (each.hasNext()) {
MatOfPoint contour = each.next();
MatOfPoint2f areaPoints = new MatOfPoint2f(contour.toArray());
RotatedRect boundingRect = Imgproc.minAreaRect(areaPoints);
Point rect_points[] = new Point[4];
boundingRect.points(rect_points);
for(int i=0; i<4; ++i){
Imgproc.line(mSourceImageMat, rect_points[i], rect_points[(i+1)%4], new Scalar(255,0,0), 2);
}
holesCount++;
Imgproc.putText(mSourceImageMat, Integer.toString(holesCount), new Point(boundingRect.center.x + 20, boundingRect.center.y),
Core.FONT_HERSHEY_PLAIN, 1.5 ,new Scalar(255, 0, 0));
// case of "twin" hole (like 9 & 10) on image
if (Imgproc.contourArea(contour) > 1.3f * averageArea) {
holesCount++;
Imgproc.putText(mSourceImageMat, ", " + Integer.toString(holesCount), new Point(boundingRect.center.x + 40, boundingRect.center.y),
Core.FONT_HERSHEY_PLAIN, 1.5 ,new Scalar(255, 0, 0));
}
}
// convert to bitmap:
Utils.matToBitmap(mSourceImageMat, bm);
mImageView.setImageBitmap(bm);
// release
frameV.release();
mat.release();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onPostResume() {
super.onPostResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, mOpenCVLoaderCallback);
}
private BaseLoaderCallback mOpenCVLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS: {
Log.i(TAG, "OpenCV loaded successfully");
mProcessButton.setVisibility(View.VISIBLE);
} break;
default: {
super.onManagerConnected(status);
} break;
}
}
};
}
如果您按FIND HOLES
Button
,您会得到如下结果
And if You press FIND HOLES
Button
You get result like this
对于其他图像,您应该在
中调整245, 255
值
For other images You should adjust 245, 255
values in
Imgproc.threshold(frameV, frameV, 245, 255, Imgproc.THRESH_BINARY);
行.
更新:MainActivity
布局(activity_main.xml
):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:id="@+id/target_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
app:srcCompat="@drawable/target"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_above="@+id/process_button"/>
<Button
android:id="@+id/process_button"
android:text="Find holes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
这篇关于如何使用Android Opencv检测目标上的弹孔的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!