Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Share:
Notifications
Clear all

[Solved] Lazarus Pascal - macOS - Use CoreImage and VisionKit to detect almost any barcode in a picture

1 Posts
1 Users
0 Reactions
1,211 Views
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2858
Topic starter  

As I was playing with QR codes (see previous post on scanning QR codes with CoreImage), I figured out how to use the VisionKit to rapidly detect pretty much any barcode, QR codes included.

Since it took me a while to figure things out, I thought I'd share it here in the hoped it is helpful for someone. At least it is a good reference for myself 😊 

This is a super small project that detects multiple barcodes and QR codes very fast.

The form is simple: a TButton, a TImage, a TMemo and a TOpenDialog.

It allows you to select a picture file (for example a JPG or PNG) and uses VisionKit to detect the barcodes.
The found results will be listed in the TMemo.

Notes:
- this may require macOS 13 (VisionKit)
- you may need to set the compiler option "-WM11.0" or even "-WM13.0"
- in my example image it detected 9 out of 12 barcodes, not sure if 9 is the max it can detect in one image or if the missing 3 formats are not supported.

unit Unit1;

{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$modeswitch objectivec2}
{$modeswitch cvar}
{$modeswitch cblocks}
{$packrecords c}
{$linkframework vision}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls
  , CocoaAll, CocoaUtils;

type
  { TForm1 }

  TForm1 = class(TForm)
    btnDetectBarcode: TButton;
    Image1: TImage;
    Memo1: TMemo;
    OpenDialog1: TOpenDialog;
    procedure btnDetectBarcodeClick(Sender: TObject);
  private

  public

  end;

type
  VNRequest = objcclass external (NSObject)
  end;

  VNDetectBarcodesRequest = objcclass external (VNRequest)
    function init: id; message 'init';
    function results: NSArray; message 'results';
  end;

  VNBarcodeObservation = objcclass external (NSObject)
    function payloadStringValue: NSString; message 'payloadStringValue';
  end;

  VNImageRequestHandler = objcclass external (NSObject)
    function initWithURL(url: NSURL; options: NSDictionary): id; message 'initWithURL:options:';
    function performRequests(requests: NSArray; error: NSErrorPtr): boolean; message 'performRequests:error:';
  end;


var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.btnDetectBarcodeClick(Sender: TObject);
var
  ImagePath: NSString;
  ImageURL: NSURL;
  Request: VNDetectBarcodesRequest;
  Handler: VNImageRequestHandler;
  RequestArray: NSArray;
  Error: NSError;
  Results: NSArray;
  Barcode: VNBarcodeObservation;
  i: Integer;
  Filename: string;
begin
  if OpenDialog1.Execute then
    begin
      Filename := OpenDialog1.FileName;
      Image1.Picture.LoadFromFile(Filename);
      ImageURL := NSURL.fileURLWithPath(NSSTR(Filename));

      ImagePath := NSSTR(Filename);
      ImageURL := NSURL.fileURLWithPath(ImagePath);

      Request := VNDetectBarcodesRequest.alloc.init;
      RequestArray := NSArray.arrayWithObject(Request);

      Handler := VNImageRequestHandler.alloc.initWithURL(ImageURL, nil);
      if Handler.performRequests(RequestArray, @Error) then
      begin
        Results := Request.results;

        Memo1.Clear;
        for i := 0 to Results.count - 1 do
        begin
          Barcode := VNBarcodeObservation(Results.objectAtIndex(i));
          Memo1.Append('Barcode: '+NSStringToString(Barcode.payloadStringValue));
        end;
      end
      else
        memo1.Append('Vision request failed: '+NSStringToString(Error.localizedDescription));
    end;
end;

end.

As you can see I did a minimal interface definition to VisionKit as the SDK headers for Lazarus/MacOS are very outdated and do not include VisonKit (yet).

This topic was modified 3 weeks ago by Hans

   
ReplyQuote
Share: