Skip to content

Commit

Permalink
Improve matchtemplate multithreading
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Jul 1, 2023
1 parent 41d05f6 commit 2aa7183
Show file tree
Hide file tree
Showing 10 changed files with 708 additions and 588 deletions.
4 changes: 2 additions & 2 deletions Source/finders/simba.finder_color.pas
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ function MatchColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;

var
ColorFinderMT_Enabled: Boolean = True;
ColorFinderMT_SliceHeight: Integer = 150;
ColorFinderMT_SliceWidth: Integer = 300;
ColorFinderMT_SliceHeight: Integer = 125;
ColorFinderMT_SliceWidth: Integer = 250;

implementation

Expand Down
15 changes: 13 additions & 2 deletions Source/integermatrix.inc
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ type
function Area: Integer;
function GetSize(out AWidth, AHeight: Integer): Boolean;
procedure SetSize(AWidth, AHeight: Integer);
function Copy: TIntegerMatrix;

function Copy: TIntegerMatrix; overload;
function Copy(Y1, Y2: Integer): TIntegerMatrix; overload;
function GetValues(Indices: TPointArray): TIntegerArray;
procedure SetValues(Indices: TPointArray; Values: TIntegerArray);
procedure SetValue(Indices: TPointArray; Value: Integer);
Expand Down Expand Up @@ -62,6 +62,17 @@ begin
Result[Y] := System.Copy(Self[Y]);
end;

function TIntegerMatrixHelper.Copy(Y1, Y2: Integer): TIntegerMatrix;
var
RowSize, Y: Integer;
begin
RowSize := Width * SizeOf(Integer);

Result.SetSize(Width, Y2-Y1);
for Y := 0 to Result.Height - 1 do
Move(Self[Y1+Y, 0], Result[Y, 0], RowSize);
end;

function TIntegerMatrixHelper.GetValues(Indices: TPointArray): TIntegerArray;
var
Count, I: Integer;
Expand Down
91 changes: 71 additions & 20 deletions Source/matchtemplate/simba.matchtemplate.pas
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Mask template matching implemented from OpenCV's templmatch.cpp
[==============================================================================}
{$DEFINE SIMBA_MAX_OPTIMIZATION}
{$i simba.inc}
Expand All @@ -25,7 +22,7 @@
interface

uses
classes, sysutils,
Classes, SysUtils,
simba.mufasatypes, simba.baseclass, simba.bitmap;

type
Expand All @@ -44,10 +41,64 @@ function MatchTemplateMask(Image, Template: TIntegerMatrix; Formula: ETMFormula)

function MatchTemplate(Image, Template: TIntegerMatrix; Formula: ETMFormula): TSingleMatrix;

function CalculateSlices(SearchWidth, SearchHeight: Integer): Integer;

type
TMatchTemplate = function(Image, Template: TIntegerMatrix; Normed: Boolean): TSingleMatrix;

function Multithread(Image, Templ: TIntegerMatrix; MatchTemplate: TMatchTemplate; Normed: Boolean): TSingleMatrix;

var
MatchTemplateMT_Enabled: Boolean = True;
MatchTemplateMT_SliceHeight: Integer = 125;
MatchTemplateMT_SliceWidth: Integer = 250;

implementation

uses
simba.matchtemplate_ccorr, simba.matchtemplate_sqdiff, simba.matchtemplate_ccoeff;
simba.matchtemplate_ccorr, simba.matchtemplate_sqdiff, simba.matchtemplate_ccoeff,
simba.threadpool;

// How much to "Slice" (vertically) the image up for multithreading.
function CalculateSlices(SearchWidth, SearchHeight: Integer): Integer;
var
I: Integer;
begin
Result := 1;

if MatchTemplateMT_Enabled and (SearchWidth >= MatchTemplateMT_SliceWidth) and (SearchHeight >= (MatchTemplateMT_SliceHeight * 2)) then // not worth
begin
for I := SimbaThreadPool.ThreadCount - 1 downto 2 do
if (SearchHeight div I) > MatchTemplateMT_SliceHeight then // Each slice is at least `MatchTemplateMT_SliceHeight` pixels
Exit(I);
end;

// not possible to slice into at least `MatchTemplateMT_SliceHeight` pixels
end;

function Multithread(Image, Templ: TIntegerMatrix; MatchTemplate: TMatchTemplate; Normed: Boolean): TSingleMatrix;
var
RowSize: Integer;

procedure Execute(const Index, Lo, Hi: Integer);
var
Mat: TSingleMatrix;
Y: Integer;
begin
Mat := MatchTemplate(Image.Copy(Lo, Min(Hi + Templ.Height, Image.Height)), Templ, Normed);
for Y := 0 to Mat.Height - 1 do
Move(Mat[Y, 0], Result[Lo+Y, 0], RowSize);
end;

begin
Result.SetSize(
(Image.Width - Templ.Width) + 1,
(Image.Height - Templ.Height) + 1
);
RowSize := Result.Width * SizeOf(Single);

SimbaThreadPool.RunParallel(CalculateSlices(Image.Width, Image.Height), 0, Image.Height, @Execute);
end;

procedure Validate(ImageWidth, ImageHeight, TemplateWidth, TemplateHeight: Integer);
begin
Expand All @@ -65,11 +116,11 @@ function MatchTemplateCache(Image, Template: TIntegerMatrix; Formula: ETMFormula

case Formula of
TM_CCOEFF, TM_CCOEFF_NORMED:
Result := MatchTemplateMask_CCOEFF_CreateCache_MT(Image, Template);
Result := MatchTemplateMask_CCOEFF_CreateCache(Image, Template);
TM_CCORR, TM_CCORR_NORMED:
Result := MatchTemplateMask_CCORR_CreateCache_MT(Image, Template);
Result := MatchTemplateMask_CCORR_CreateCache(Image, Template);
TM_SQDIFF, TM_SQDIFF_NORMED:
Result := MatchTemplateMask_SQDIFF_CreateCache_MT(Image, Template);
Result := MatchTemplateMask_SQDIFF_CreateCache(Image, Template);
end;
end;

Expand Down Expand Up @@ -102,12 +153,12 @@ function MatchTemplateMask(Image, Template: TIntegerMatrix; Formula: ETMFormula)
Validate(Image.Width, Image.Height, Template.Width, Template.Height);

case Formula of
TM_CCOEFF: Result := MatchTemplateMask_CCOEFF_MT(Image, Template, False);
TM_CCOEFF_NORMED: Result := MatchTemplateMask_CCOEFF_MT(Image, Template, True);
TM_SQDIFF: Result := MatchTemplateMask_SQDIFF_MT(Image, Template, False);
TM_SQDIFF_NORMED: Result := MatchTemplateMask_SQDIFF_MT(Image, Template, True);
TM_CCORR: Result := MatchTemplateMask_CCORR_MT(Image, Template, False);
TM_CCORR_NORMED: Result := MatchTemplateMask_CCORR_MT(Image, Template, True);
TM_CCOEFF: Result := MatchTemplateMask_CCOEFF(Image, Template, False);
TM_CCOEFF_NORMED: Result := MatchTemplateMask_CCOEFF(Image, Template, True);
TM_SQDIFF: Result := MatchTemplateMask_SQDIFF(Image, Template, False);
TM_SQDIFF_NORMED: Result := MatchTemplateMask_SQDIFF(Image, Template, True);
TM_CCORR: Result := MatchTemplateMask_CCORR(Image, Template, False);
TM_CCORR_NORMED: Result := MatchTemplateMask_CCORR(Image, Template, True);
end;
end;

Expand All @@ -116,12 +167,12 @@ function MatchTemplate(Image, Template: TIntegerMatrix; Formula: ETMFormula): TS
Validate(Image.Width, Image.Height, Template.Width, Template.Height);

case Formula of
TM_CCOEFF: Result := MatchTemplate_CCOEFF_MT(Image, Template, False);
TM_CCOEFF_NORMED: Result := MatchTemplate_CCOEFF_MT(Image, Template, True);
TM_SQDIFF: Result := MatchTemplate_SQDIFF_MT(Image, Template, False);
TM_SQDIFF_NORMED: Result := MatchTemplate_SQDIFF_MT(Image, Template, True);
TM_CCORR: Result := MatchTemplate_CCORR_MT(Image, Template, False);
TM_CCORR_NORMED: Result := MatchTemplate_CCORR_MT(Image, Template, True);
TM_CCOEFF: Result := MatchTemplate_CCOEFF(Image, Template, False);
TM_CCOEFF_NORMED: Result := MatchTemplate_CCOEFF(Image, Template, True);
TM_SQDIFF: Result := MatchTemplate_SQDIFF(Image, Template, False);
TM_SQDIFF_NORMED: Result := MatchTemplate_SQDIFF(Image, Template, True);
TM_CCORR: Result := MatchTemplate_CCORR(Image, Template, False);
TM_CCORR_NORMED: Result := MatchTemplate_CCORR(Image, Template, True);
end;
end;

Expand Down
Loading

0 comments on commit 2aa7183

Please sign in to comment.