好的,所以我是一名正在忙于我的年度项目的大学生。本质上,我正在尝试做的是允许用户拥有“ x”数量的图像,这些图像将保存到其Android设备。一旦用户保存了这些图像,便可以使用相机进行“扫描”,并将实时相机视图与保存的图像进行比较,并显示一条消息“找到匹配项”或沿这些行显示的内容。
我有1张图片和只有1张图片的匹配图片。我无法弄清楚如何与多个图像进行比较。我已经尝试搜索解决方案,但是大多数解决方案与C ++或Python有关,这对我没有太大帮助,因为我无法确定如何在Android Studio中进行操作。任何帮助将不胜感激。
此处的图片Current System
PS:这是一个用于概念验证的大学项目,我在底部的匹配似乎适用于我所测试的内容,因此在此阶段我不太担心提高准确性,只允许进行多个比较图片。
public class ScanTattooActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 {
private static final String TAG = "Scan Tattoo::Activity";
private int w, h;
private CameraBridgeViewBase mOpenCvCameraView;
TextView tvName;
Scalar RED = new Scalar(255, 0, 0);
Scalar GREEN = new Scalar(0, 255, 0);
FeatureDetector detector;
DescriptorExtractor descriptor;
DescriptorMatcher matcher;
Mat descriptors2,descriptors1;
Mat img1;
MatOfKeyPoint keypoints1,keypoints2;
int match_count = 0;
static {
if (!OpenCVLoader.initDebug())
Log.d("ERROR", "Unable to load OpenCV");
else
Log.d("SUCCESS", "OpenCV loaded");
}
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS: {
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
try {
initializeOpenCVDependencies();
} catch (IOException e) {
e.printStackTrace();
}
}
break;
default: {
super.onManagerConnected(status);
}
break;
}
}
};
private void initializeOpenCVDependencies() throws IOException {
mOpenCvCameraView.enableView();
detector = FeatureDetector.create(FeatureDetector.ORB);
descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
img1 = new Mat();
AssetManager assetManager = getAssets();
InputStream istr = assetManager.open("ajpeg2.jpg");
Bitmap bitmap = BitmapFactory.decodeStream(istr);
Utils.bitmapToMat(bitmap, img1);
Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGB2GRAY);
img1.convertTo(img1, 0); //converting the image to match with the type of the cameras image
descriptors1 = new Mat();
keypoints1 = new MatOfKeyPoint();
detector.detect(img1, keypoints1);
descriptor.compute(img1, keypoints1, descriptors1);
}
public ScanTattooActivity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_scan_tattoo);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.scantattoo_activity_java_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
//tvName = (TextView) findViewById(R.id.text1);
}
@Override
public void onPause() {
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onResume() {
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
public void onCameraViewStarted(int width, int height) {
w = width;
h = height;
}
public void onCameraViewStopped() {
}
public Mat recognize(Mat aInputFrame) {
Imgproc.cvtColor(aInputFrame, aInputFrame, Imgproc.COLOR_RGB2GRAY);
descriptors2 = new Mat();
keypoints2 = new MatOfKeyPoint();
detector.detect(aInputFrame, keypoints2);
descriptor.compute(aInputFrame, keypoints2, descriptors2);
int count = 0;
// Matching
MatOfDMatch matches = new MatOfDMatch();
if (img1.type() == aInputFrame.type()) {
matcher.match(descriptors1, descriptors2, matches);
} else {
return aInputFrame;
}
List<DMatch> matchesList = matches.toList();
Double max_dist = 0.0;
Double min_dist = 100.0;
for (int i = 0; i < matchesList.size(); i++) {
Double dist = (double) matchesList.get(i).distance;
if (dist < min_dist)
min_dist = dist;
if (dist > max_dist)
max_dist = dist;
}
double goodMatchesSum = 0;
LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
for (int i = 0; i < matchesList.size(); i++) {
if (matchesList.get(i).distance <= (1.5 * min_dist))
good_matches.addLast(matchesList.get(i));
goodMatchesSum += matchesList.get(i).distance;
count ++;
}
MatOfDMatch goodMatches = new MatOfDMatch();
goodMatches.fromList(good_matches);
Mat outputImg = new Mat();
MatOfByte drawnMatches = new MatOfByte();
if (aInputFrame.empty() || aInputFrame.cols() < 1 || aInputFrame.rows() < 1) {
return aInputFrame;
}
Features2d.drawMatches(img1, keypoints1, aInputFrame, keypoints2, goodMatches, outputImg, GREEN, RED, drawnMatches, Features2d.NOT_DRAW_SINGLE_POINTS);
Imgproc.resize(outputImg, outputImg, aInputFrame.size());
double matchPercentage = goodMatchesSum/ (double) good_matches.size();
if(matchPercentage/count >= 5)
{
match_count ++;
if(match_count > 20)
{
"good match"
}
}
else if (matchPercentage/count < 5)
{
"Bad match, compare next image"
}
return outputImg;
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
return recognize(inputFrame.rgba());
}
}