如何在Android中创建Google Lens应用程序?
从照片或视频流中提取和分析文本的能力是一项宝贵的技能,可以显著提高Android应用程序的功能和用户体验。Google Lens是Google开发的一项先进的图像识别和增强现实技术,就是一个著名的例子。虽然复制Google Lens的全部功能是一项艰巨的任务,但我们可以研究一个更简单的实现,该实现使用Google Vision API在Android应用程序中专注于文本识别。
使用的方法
在Android中使用Google Vision API进行文本识别
在Android中使用Google Vision API进行文本识别
算法
步骤1 - 设置布局。
设计活动布局。创建一个包含用于相机预览的SurfaceView和用于显示识别文本的TextView的布局文件。
步骤2 - 创建活动。
创建一个新的活动类;我们将其命名为GoogleLensActivity。
在onCreate()方法中,初始化相机并在SurfaceView上启动相机预览。
设置相机回调,以便在相机预览可用时捕获图像。
步骤3 - 显示识别的文本。
实现文本识别器。Processor接口处理文本识别过程。
在TextRecognizer.Processor的receiveDetections()方法中,使用从相机图像中识别的文本更新识别的文本TextView。
步骤4 - 更新布局和清单。
更新布局XML文件以包含必要的视图(SurfaceView和TextView)。
向应用程序的AndroidManifest.xml文件中添加相机和互联网权限。
XML代码
<!-- below line is use to add camera feature in our app --> <uses-feature android:name="android.hardware.camera" android:required="true" /> <!-- permission for internet --> <uses-permission android:name="android.permission.INTERNET" />
<meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="label" />
XML程序
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.googlelens"> <!-- below line is use to add camera feature in our app --> <uses-feature android:name="android.hardware.camera" android:required="true" /> <!-- permission for internet --> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.GoogleLens"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="label" /> </application> </manifest>
XML程序
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" tools:context=".MainActivity"> <!--image view for displaying our image--> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="300dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:scaleType="centerCrop" /> <LinearLayout android:id="@+id/idLLButtons" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/image" android:orientation="horizontal"> <!--button for capturing our image--> <Button android:id="@+id/snapbtn" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="5dp" android:layout_marginTop="30dp" android:layout_weight="1" android:lines="2" android:text="Snap" android:textAllCaps="false" android:textSize="18sp" android:textStyle="bold" /> <!--button for detecting the objects--> <Button android:id="@+id/idBtnSearchResuts" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="5dp" android:layout_marginTop="30dp" android:layout_weight="1" android:lines="2" android:text="Get Search Results" android:textAllCaps="false" android:textSize="18sp" android:textStyle="bold" /> </LinearLayout> <!--recycler view for displaying the list of result--> <androidx.recyclerview.widget.RecyclerView android:id="@+id/idRVSearchResults" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/idLLButtons" /> </RelativeLayout>
Java程序
import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.Volley; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.ml.vision.FirebaseVision; import com.google.firebase.ml.vision.common.FirebaseVisionImage; import com.google.firebase.ml.vision.label.FirebaseVisionImageLabel; import com.google.firebase.ml.vision.label.FirebaseVisionImageLabeler; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { static final int REQUEST_IMAGE_CAPTURE = 1; // variables for our image view, image bitmap, // buttons, recycler view, adapter and array list. private ImageView img; private Button snap, searchResultsBtn; private Bitmap imageBitmap; private RecyclerView resultRV; private SearchResultsRVAdapter searchResultsRVAdapter; private ArrayList<DataModal> dataModalArrayList; private String title, link, displayed_link, snippet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // initializing all our variables for views img = (ImageView) findViewById(R.id.image); snap = (Button) findViewById(R.id.snapbtn); searchResultsBtn = findViewById(R.id.idBtnSearchResuts); resultRV = findViewById(R.id.idRVSearchResults); // initializing our array list dataModalArrayList = new ArrayList<>(); // initializing our adapter class. searchResultsRVAdapter = new SearchResultsRVAdapter(dataModalArrayList, MainActivity.this); // layout manager for our recycler view. LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false); // on below line we are setting layout manager // and adapter to our recycler view. resultRV.setLayoutManager(manager); resultRV.setAdapter(searchResultsRVAdapter); // adding on click listener for our snap button. snap.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // calling a method to capture an image. dispatchTakePictureIntent(); } }); // adding on click listener for our button to search data. searchResultsBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // calling a method to get search results. getResults(); } }); } private void getResults() { // inside the label image method we are calling a firebase vision image // and passing our image bitmap to it. FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(imageBitmap); // on below line we are creating a labeler for our image bitmap and // creating a variable for our firebase vision image labeler. FirebaseVisionImageLabeler labeler = FirebaseVision.getInstance().getOnDeviceImageLabeler(); // calling a method to process an image and adding on success listener method to it. labeler.processImage(image).addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionImageLabel>>() { @Override public void onSuccess(List<FirebaseVisionImageLabel> firebaseVisionImageLabels) { String searchQuery = firebaseVisionImageLabels.get(0).getText(); searchData(searchQuery); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // displaying error message. Toast.makeText(MainActivity.this, "Fail to detect image..", Toast.LENGTH_SHORT).show(); } }); } private void searchData(String searchQuery) { String apiKey = "Enter your API key here"; String url = "https://serpapi.com/search.json?q=" + searchQuery.trim() + "&location=Delhi,India&hl=en&gl=us&google_domain=google.com&api_key=" + apiKey; // creating a new variable for our request queue RequestQueue queue = Volley.newRequestQueue(MainActivity.this); JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { // on below line we are extracting data from our json. JSONArray organicResultsArray = response.getJSONArray("organic_results"); for (int i = 0; i < organicResultsArray.length(); i++) { JSONObject organicObj = organicResultsArray.getJSONObject(i); if (organicObj.has("title")) { title = organicObj.getString("title"); } if (organicObj.has("link")) { link = organicObj.getString("link"); } if (organicObj.has("displayed_link")) { displayed_link = organicObj.getString("displayed_link"); } if (organicObj.has("snippet")) { snippet = organicObj.getString("snippet"); } // on below line we are adding data to our array list. dataModalArrayList.add(new DataModal(title, link, displayed_link, snippet)); } // notifying our adapter class // on data change in array list. searchResultsRVAdapter.notifyDataSetChanged(); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // displaying error message. Toast.makeText(MainActivity.this, "No Result found for the search query..", Toast.LENGTH_SHORT).show(); } }); // adding json object request to our queue. queue.add(jsonObjectRequest); } // method to capture image. private void dispatchTakePictureIntent() { // inside this method we are calling an implicit intent to capture an image. Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { // calling a start activity for result when image is captured. startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // inside on activity result method we are // setting our image to our image view from bitmap. if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { Bundle extras = data.getExtras(); imageBitmap = (Bitmap) extras.get("data"); // on below line we are setting our // bitmap to our image view. img.setImageBitmap(imageBitmap); } } }
输出
结论
本文旨在介绍如何使用Google Vision API进行内容识别,并根据您的特定应用程序需求提供大量的修改和扩展空间。您可以通过添加诸如语言翻译、实体识别和问题识别等功能来增强其实用性。文本识别提供了无限的可能性,使您可以创建能够从图像中提取和翻译内容、辅助视力障碍用户、自动化数据输入等等的应用程序。