Commit 29d124ff authored by junweifu's avatar junweifu Committed by Commit Bot

ShapeDetection: Detect barcode informations by VNDetectBarcodesRequest

The native request first locates all barcodes in the input image, then analyzes
each to decode payload. The bounding box of the detected barcode are normalized
to the dimensions of the processed image, so the coordinates need to be
converted.
Forward declaring the necessary symbols in sdk_forward_declarations.h.

BUG=848182

Cq-Include-Trybots: luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win10_chromium_x64_rel_ng
Change-Id: I03b966a1886feaf64a87e778396ad96e3d16b85e
Reviewed-on: https://chromium-review.googlesource.com/1142831Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Commit-Queue: Junwei Fu <junwei.fu@intel.com>
Cr-Commit-Position: refs/heads/master@{#577368}
parent 37d98c47
......@@ -322,6 +322,21 @@ typedef NSString* VNImageOption NS_STRING_ENUM;
@property(readonly, nonatomic, strong) VNFaceLandmarks2D* landmarks;
@end
// VNDetectBarcodesRequest forward declarations.
typedef NSString* VNBarcodeSymbology NS_STRING_ENUM;
@interface VNDetectBarcodesRequest : VNImageBasedRequest
@property(readwrite, nonatomic, copy) NSArray<VNBarcodeSymbology>* symbologies;
@end
// VNBarcodeObservation forward declarations.
@interface VNRectangleObservation : VNDetectedObjectObservation
@end
@interface VNBarcodeObservation : VNRectangleObservation
@property(readonly, nonatomic, copy) NSString* payloadStringValue;
@end
#endif // MAC_OS_X_VERSION_10_13
// ----------------------------------------------------------------------------
// The symbol for kCWSSIDDidChangeNotification is available in the
......
......@@ -65,8 +65,7 @@ struct TestParams {
BarcodeDetectorFactory factory;
} kTestParams[] = {
{1, kInfoString, base::Bind(&CreateBarcodeDetectorImplMac)},
// TODO(junwei.fu): add more tests https://crbug.com/848182.
{0, "", base::Bind(&CreateBarcodeDetectorImplMacVision)},
{1, kInfoString, base::Bind(&CreateBarcodeDetectorImplMacVision)},
};
}
......
......@@ -5,8 +5,15 @@
#ifndef SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_IMPL_MAC_VISION_H_
#define SERVICES_SHAPE_DETECTION_BARCODE_DETECTION_IMPL_MAC_VISION_H_
#include <memory>
#include <utility>
#include "base/mac/availability.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/shape_detection/detection_utils_mac.h"
#include "services/shape_detection/public/mojom/barcodedetection.mojom.h"
#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h"
......@@ -26,7 +33,19 @@ class API_AVAILABLE(macos(10.13)) BarcodeDetectionImplMacVision
void Detect(const SkBitmap& bitmap,
mojom::BarcodeDetection::DetectCallback callback) override;
void SetBinding(mojo::StrongBindingPtr<mojom::BarcodeDetection> binding) {
binding_ = std::move(binding);
}
private:
void OnBarcodesDetected(VNRequest* request, NSError* error);
CGSize image_size_;
std::unique_ptr<VisionAPIAsyncRequestMac> barcodes_async_request_;
DetectCallback detected_callback_;
mojo::StrongBindingPtr<mojom::BarcodeDetection> binding_;
base::WeakPtrFactory<BarcodeDetectionImplMacVision> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BarcodeDetectionImplMacVision);
};
......
......@@ -5,26 +5,80 @@
#include "services/shape_detection/barcode_detection_impl_mac_vision.h"
#include <Foundation/Foundation.h>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace shape_detection {
BarcodeDetectionImplMacVision::BarcodeDetectionImplMacVision(
mojom::BarcodeDetectorOptionsPtr options) {
mojom::BarcodeDetectorOptionsPtr options)
: weak_factory_(this) {
Class request_class = NSClassFromString(@"VNDetectBarcodesRequest");
if (!request_class) {
DLOG(ERROR) << "Failed to load VNDetectBarcodesRequest class";
return;
}
// The repeating callback will not be run if BarcodeDetectionImplMacVision
// object has already been destroyed.
barcodes_async_request_ = VisionAPIAsyncRequestMac::Create(
request_class,
base::BindRepeating(&BarcodeDetectionImplMacVision::OnBarcodesDetected,
weak_factory_.GetWeakPtr()));
}
BarcodeDetectionImplMacVision::~BarcodeDetectionImplMacVision() = default;
void BarcodeDetectionImplMacVision::Detect(const SkBitmap& bitmap,
DetectCallback callback) {
std::move(callback).Run({});
DCHECK(barcodes_async_request_);
if (!barcodes_async_request_->PerformRequest(bitmap)) {
std::move(callback).Run({});
return;
}
image_size_ = CGSizeMake(bitmap.width(), bitmap.height());
// Hold on the callback until async request completes.
detected_callback_ = std::move(callback);
// This prevents the Detect function from being called before the
// VisionAPIAsyncRequestMac completes.
if (binding_) // Can be unbound in unit testing.
binding_->PauseIncomingMethodCallProcessing();
}
void BarcodeDetectionImplMacVision::OnBarcodesDetected(VNRequest* request,
NSError* error) {
if (binding_) // Can be unbound in unit testing.
binding_->ResumeIncomingMethodCallProcessing();
if ([request.results count] == 0 || error) {
std::move(detected_callback_).Run({});
return;
}
std::vector<mojom::BarcodeDetectionResultPtr> results;
for (VNBarcodeObservation* const observation in request.results) {
auto barcode = mojom::BarcodeDetectionResult::New();
// The coordinates are normalized to the dimensions of the processed image.
barcode->bounding_box = ConvertCGToGfxCoordinates(
CGRectMake(observation.boundingBox.origin.x * image_size_.width,
observation.boundingBox.origin.y * image_size_.height,
observation.boundingBox.size.width * image_size_.width,
observation.boundingBox.size.height * image_size_.height),
image_size_.height);
barcode->raw_value =
base::SysNSStringToUTF8(observation.payloadStringValue);
results.push_back(std::move(barcode));
}
std::move(detected_callback_).Run(std::move(results));
}
} // namespace shape_detection
......@@ -30,9 +30,11 @@ void BarcodeDetectionProviderMac::CreateBarcodeDetection(
mojom::BarcodeDetectorOptionsPtr options) {
// Vision Framework needs at least MAC OS X 10.13.
if (@available(macOS 10.13, *)) {
mojo::MakeStrongBinding(
std::make_unique<BarcodeDetectionImplMacVision>(std::move(options)),
std::move(request));
auto impl =
std::make_unique<BarcodeDetectionImplMacVision>(std::move(options));
auto* impl_ptr = impl.get();
impl_ptr->SetBinding(
mojo::MakeStrongBinding(std::move(impl), std::move(request)));
return;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment