Implementing Product Visual Search
A picture is worth a thousand words. See how to turn pictures into product information for users.
Join the DZone community and get the full member experience.
Join For FreeUse Case
We will capture a product image from our developed shopping application using a device camera.
- We will show the returned products list.
Prerequisites
Java JDK 1.8 or higher is recommended.
Android Studio is recommended.
Huawei Android device with HMS core 4.0.0.300 or higher.
Before developing an app, you will need to register as a HUAWEI developer.
Integrating the App Gallery Connect (AGC) SDK.
Implementation
1. Enable the ML kit in Manage APIs.
2. Integrate the following dependencies in the app-level build.gradle.
// Import the product visual search SDK.
implementation 'com.huawei.hms:ml-computer-vision-cloud:2.0.1.300'
3. Add the AGC plugin at the top of the app.gradle file.
xxxxxxxxxx
apply plugin: 'com.huawei.agconnect'
4. Add the following permissions in the manifest.
Camera permission: android.permission.CAMERA: Obtains real-time images or videos from a camera.
Internet access permission: android.permission.INTERNET: Accesses cloud services on the Internet.
Storage write permission: android.permission.WRITE_EXTERNAL_STORAGE: Upgrades the algorithm version.
Storage read permission: android.permission.READ_EXTERNAL_STORAGE: Reads photos stored on a device.
5. To request camera permission in realtime.
xxxxxxxxxx
private void requestCameraPermission() {
final String[] permissions = new String[] {Manifest.permission.CAMERA};
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
ActivityCompat.requestPermissions(this, permissions, this.CAMERA_PERMISSION_CODE);
return;
}
}
6. Add the following code in the Application class
xxxxxxxxxx
public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
MLApplication.getInstance().setApiKey("API KEY");
}
}
The API key can be obtained either from AGC or the integrated agcconnect-services.json.
7. To create an analyzer for our product visual search.
xxxxxxxxxx
private void initializeProductVisionSearch() {
MLRemoteProductVisionSearchAnalyzerSetting settings = new MLRemoteProductVisionSearchAnalyzerSetting.Factory()
// Set the maximum number of products that can be returned.
.setLargestNumOfReturns(16)
// Set the product set ID. (Contact mlkit@huawei.com to obtain the configuration guide.)
// .setProductSetId(productSetId)
// Set the region.
.setRegion(MLRemoteProductVisionSearchAnalyzerSetting.REGION_DR_CHINA)
.create();
analyzer
= MLAnalyzerFactory.getInstance().getRemoteProductVisionSearchAnalyzer(settings);
}
8. To capture an image from a camera.
xxxxxxxxxx
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQ_CAMERA_CODE);
9. Once the image has been captured, the onActivityResult() method will be executed.
xxxxxxxxxx
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult");
if(requestCode == 101) {
if (resultCode == RESULT_OK) {
Bitmap bitmap = (Bitmap) data.getExtras().get("data");
if (bitmap != null) {
// Create an MLFrame object using the bitmap, which is the image data in bitmap format.
MLFrame mlFrame = new MLFrame.Creator().setBitmap(bitmap).create();
mlImageDetection(mlFrame);
}
}
}
}
private void mlImageDetection(MLFrame mlFrame) {
Task> task = analyzer.asyncAnalyseFrame(mlFrame);
task.addOnSuccessListener(new OnSuccessListener>() {
public void onSuccess(List products) {
// Processing logic for detection success.
displaySuccess(products);
}})
.addOnFailureListener(new OnFailureListener() {
public void onFailure(Exception e) {
// Processing logic for detection failure.
// Recognition failure.
try {
MLException mlException = (MLException)e;
// Obtain the result code. You can process the result code and customize respective messages displayed to users.
int errorCode = mlException.getErrCode();
// Obtain the error information. You can quickly locate the fault based on the result code.
String errorMessage = mlException.getMessage();
} catch (Exception error) {
// Handle the conversion error.
}
}
});
}
private void displaySuccess(List productVisionSearchList) {
List productImageList = new ArrayList();
String prodcutType = "";
for (MLProductVisionSearch productVisionSearch : productVisionSearchList) {
Log.d(TAG, "type: " + productVisionSearch.getType() );
prodcutType = productVisionSearch.getType();
for (MLVisionSearchProduct product : productVisionSearch.getProductList()) {
productImageList.addAll(product.getImageList());
Log.d(TAG, "custom content: " + product.getCustomContent() );
}
}
StringBuffer buffer = new StringBuffer();
for (MLVisionSearchProductImage productImage : productImageList) {
String str = "ProductID: " + productImage.getProductId() + "
ImageID: " + productImage.getImageId() + "
Possibility: " + productImage.getPossibility();
buffer.append(str);
buffer.append("
");
}
Log.d(TAG , "display success: " + buffer.toString());
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.main_fragment_container, new SearchResultFragment(productImageList, prodcutType ));
transaction.commit();
}
The onSuccess() callback will give us a list of MLProductVisionSearch objects, which can be used to get the product id and image URL of each product. Also, we can get the product type using productVisionSearch.getType(). getType(), which returns numbers that can be mapped.
10. We can achieve the product type mapping with the following code.
xxxxxxxxxx
private String getProductType(String type) {
switch(type) {
case "0":
return "Others";
case "1":
return "Clothing";
case "2":
return "Shoes";
case "3":
return "Bags";
case "4":
return "Digital & Home appliances";
case "5":
return "Household Products";
case "6":
return "Toys";
case "7":
return "Cosmetics";
case "8":
return "Accessories";
case "9":
return "Food";
}
return "Others";
}
11. To get product id and image URL from MLVisionSearchProductImage.
xxxxxxxxxx
public void onBindViewHolder(ViewHolder holder, int position) {
final MLVisionSearchProductImage mlProductVisionSearch = productVisionSearchList.get(position);
holder.tvTitle.setText(mlProductVisionSearch.getProductId());
Glide.with(context)
.load(mlProductVisionSearch.getImageId())
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.imageView);
}
Images
Opinions expressed by DZone contributors are their own.
Comments