Resource

Resource Basics

Resource Name Filter Overlapping Areas
Resource Version 1.0
Category Filter Script
Downloads 650
Release Date 9/15/2022 11:49:39 AM
 

Resource Details

Description This filter allows to filter a set of thumbnails and returns all thumbs that have overlapping areas defined for them.

It is possible to configure the threshold. All images with overlapping areas above the threshold will be returned.
Installation Instructions na
Usage Instructions Select the script in the Filter Bar -> Filter Button 0> From Repository
Changes in this version n.a.
Special Requirements PSU 7.3.1.4521 or up
 

Author Information

Author Name IDimager Support
 

Script

const
  cFormWidth  = 350;
  cFormHeight = 150;

var
  FThreshold: Integer;
  FAreaIndex: TStringList;

  AForm: TvxSceneForm;
  AFormCaption: String;
  AThreshold: TvxNumberBox;

function BuildForm: TvxSceneForm;
var
  ALabel: TvxLabel;
  AEdit: TvxTextBox;
  ACombo: TvxPopupBox;
  AOk: TvxButton;
  ASave: TvxButton;
  ALoad: TvxButton;
  AMacroButton: TvxButton;
  ASampleButton: TvxButton;
begin
  result := TvxSceneForm.Create(nil);
  result.Caption  := AFormCaption;
  result.Position := poScreenCenter;
  result.Width := Round(cFormWidth * result.DPIFactor);
  result.Height := Round(cFormHeight * result.DPIFactor);

  ALabel := TvxLabel.Create(result.Root);
  result.Root.AddObject(ALabel);
  ALabel.Text := 'Overlap Threshold %';
  ALabel.TextAlign := vgTextAlignNear;
  ALabel.Position.Point := vgPoint(20, 20);

  AEdit := TvxNumberBox.Create(result.Root);
  result.Root.AddObject(AEdit);
  TvxNumberBox(AEdit).Min := 1;
  TvxNumberBox(AEdit).Max := 100;
  AEdit.Width := 200;
  TvxNumberBox(AEdit).Value := FThreshold;
  AEdit.Position.Point := vgPoint(ALabel.Position.X, ALabel.Position.Y + ALabel.Height + 0);
  AThreshold := AEdit;

  AOk := TvxButton.Create(result.Root);
  result.Root.AddObject(AOk);
  AOk.ModalResult := mrOk;
  AOk.Position.Point := vgPoint(AEdit.Position.X, (result.Height / result.DPIFactor) - 10 - AOk.Height);
  AOk.Text := 'OK';
  AOk.Default := True;
end;

function Initialize: Boolean;
begin
  result := True;

  FAreaIndex := TStringList.Create;

  FHit := 0;
  FThreshold    := 10;  // allow overlap of 10%
  FThreshold    := ReadFromRegistry ('Scripts', 'FilterOverlapAreas', FThreshold);

  AFormCaption := 'Filter Overlapping Areas';
  AForm := BuildForm;
  AForm.ShowModal;
  result := (AForm.ModalResult = mrOk);
  if result then
    FThreshold := Trim(AThreshold.Value);
  AForm.Free;
end;

procedure Finalize;
var
  i: Integer;
begin
  WriteToRegistry ('Scripts', 'FilterOverlapAreas', FThreshold);

  for i := 0 to FAreaIndex.Count - 1 do
  begin
    FAreaIndex.Objects[i].Free;
    FAreaIndex.Objects[i] := nil;
  end;

  FAreaIndex.Free;
end;

function FindAreasForImage(AImage: TImageItem): TCatalogAreas;
var
  AIdx: Integer;
begin
  AIdx := FAreaIndex.IndexOf(AImage.GUID);
  if AIdx = -1 then
  begin
    result := TCatalogAreas.Create(TCatalogArea, '');
    FAreaIndex.AddObject(AImage.GUID, result);
    PublicCatalog.EnumAreasForImage(AImage, result);
  end
  else
    result := TCatalogAreas(FAreaIndex.Objects[AIdx]);
end;

function HasAreaOverlap(AAreas: TCatalogAreas; AThreshold: Integer): Boolean;
var
  i, j: Integer;
  ARect1, ARect2, AOverlap: TvxRect;
  ARect1Surface, ARect2Surface, AOverlapSurface: Double;
  AThresholdFactor: Double;
begin
  result := False;

  AThresholdFactor := AThreshold / 100;

  for i := 0 to AAreas.Count - 1 do
  begin
    ARect1 := vgRect(
                      AAreas.Items[i].AreaLeft,
                      AAreas.Items[i].AreaTop,
                      AAreas.Items[i].AreaRight,
                      AAreas.Items[i].AreaBottom
                    );
    ARect1Surface := vgRectWidth(ARect1) * vgRectHeight(ARect1);
    if ARect1Surface > 0.0 then
    begin
      for j := 0 to AAreas.Count - 1 do
      begin
        if i = j then Continue;

        ARect2 := vgRect(
                          AAreas.Items[j].AreaLeft,
                          AAreas.Items[j].AreaTop,
                          AAreas.Items[j].AreaRight,
                          AAreas.Items[j].AreaBottom
                        );

        ARect2Surface := vgRectWidth(ARect2) * vgRectHeight(ARect2);
        if ARect2Surface > 0.0 then
        begin
          AOverlap := vgRect(0, 0, 0, 0);
          if vgIntersectRect(AOverlap, ARect1, ARect2) then
          begin
            // check the threshold
            AOverlapSurface := vgRectWidth(AOverlap) * vgRectHeight(AOverlap);

            if (AOverlapSurface / ARect1Surface) > AThresholdFactor then
              result := True;
          end;
        end;

        if result then break;
      end;
    end;

    if result then break;
  end;
end;

procedure BeforeFilter;
begin
  Screen.Cursor := crHourglass;
end;

procedure AfterFilter;
begin
  Screen.Cursor := crDefault;
end;

function Filter(AItem: TImageItem): Boolean;
var
  AAreas: TCatalogAreas;
begin
  result := False;
  if (FThreshold < 0) or (FThreshold > 100) then
    exit;

  AAreas := FindAreasForImage(AItem);
  if AAreas.Count = 0 then
    exit;

  result := HasAreaOverlap(AAreas, FThreshold);
end;