I made this one for a PureBasic user a while ago, maybe it helps for your problem, too, as the usage of summed area tables or integral images is good when comparing two images, but here we find a sub image:
Code:
EnableExplicit
Structure RGB
R.l
G.l
B.l
EndStructure
Structure IntegralImage
Width.i
Height.i
*ValuesPointer.i
EndStructure
Procedure.i IntegralImage(PBImage.i, *Image.IntegralImage)
Protected Color.i
Protected *Cursor.RGB
Protected *CursorAbove.RGB
Protected *CursorAboveLeft.RGB
Protected *CursorLeft.RGB
Protected X.i, Y.i
If Not IsImage(PBImage)
ProcedureReturn #False
EndIf
*Image\Width = ImageWidth(PBImage)
*Image\Height = ImageHeight(PBImage)
*Image\ValuesPointer = AllocateMemory(*Image\Width * *Image\Height * SizeOf(RGB))
If *Image\ValuesPointer = #Null
ProcedureReturn #False
EndIf
*Cursor = *Image\ValuesPointer
*CursorAbove = *Image\ValuesPointer - *Image\Width * SizeOf(RGB)
*CursorAboveLeft = *Image\ValuesPointer - *Image\Width * SizeOf(RGB) - SizeOf(RGB)
*CursorLeft = *Image\ValuesPointer - SizeOf(RGB)
StartDrawing(ImageOutput(PBImage))
For Y = 0 To OutputHeight() - 1
For X = 0 To OutputWidth() - 1
Color = Point(X, Y)
*Cursor\R = Red(Color)
*Cursor\G = Green(Color)
*Cursor\B = Blue(Color)
If X > 0
*Cursor\R + *CursorLeft\R
*Cursor\G + *CursorLeft\G
*Cursor\B + *CursorLeft\B
If Y > 0
*Cursor\R - *CursorAboveLeft\R
*Cursor\G - *CursorAboveLeft\G
*Cursor\B - *CursorAboveLeft\B
EndIf
EndIf
If Y > 0
*Cursor\R + *CursorAbove\R
*Cursor\G + *CursorAbove\G
*Cursor\B + *CursorAbove\B
EndIf
*CursorLeft + SizeOf(RGB)
*CursorAbove + SizeOf(RGB)
*CursorAboveLeft + SizeOf(RGB)
*Cursor + SizeOf(RGB)
Next X
Next Y
StopDrawing()
ProcedureReturn #True
EndProcedure
Procedure.i ToPBImage(*Image.IntegralImage, PBImage.i)
Protected X.i, Y.i
Protected Result.i
Protected *Cursor.RGB
Protected Max.RGB
Result = CreateImage(PBImage, *Image\Width, *Image\Height)
If PBImage = #PB_Any : PBImage = Result : EndIf
StartDrawing(ImageOutput(PBImage))
*Cursor = *Image\ValuesPointer
CopyStructure(*Image\ValuesPointer + OutputWidth() * OutputHeight() * SizeOf(RGB) - SizeOf(RGB), @Max, RGB)
For Y = 0 To OutputHeight() - 1
For X = 0 To OutputWidth() - 1
Plot(X, Y, RGB(*Cursor\R * 255 / Max\R, *Cursor\G * 255 / Max\G, *Cursor\B * 255 / Max\B))
*Cursor + SizeOf(RGB)
Next X
Next Y
StopDrawing()
ProcedureReturn Result
EndProcedure
Procedure.i GetMeanColor(*Image.IntegralImage, X.i, Y.i, Width.i, Height.i)
Protected ResultRGB.RGB
Protected *RGBPointer.RGB
Protected Result.i = 0
Protected Right.i, Bottom.i
Protected Index.i
Protected Factor.d
Right = X + Width - 1
Bottom = Y + Height - 1
Index = Right + Bottom * *Image\Width
If Index >= 0
CopyStructure(*Image\ValuesPointer + Index * SizeOf(RGB), @ResultRGB, RGB)
EndIf
Index = X + Bottom * *Image\Width
If Index >= 0
*RGBPointer = *Image\ValuesPointer + Index * SizeOf(RGB)
ResultRGB\R - *RGBPointer\R
ResultRGB\G - *RGBPointer\G
ResultRGB\B - *RGBPointer\B
EndIf
Index = X + Y * *Image\Width
If Index >= 0
*RGBPointer = *Image\ValuesPointer + Index * SizeOf(RGB)
ResultRGB\R + *RGBPointer\R
ResultRGB\G + *RGBPointer\G
ResultRGB\B + *RGBPointer\B
EndIf
Index = Right + Y * *Image\Width
If Index >= 0
*RGBPointer = *Image\ValuesPointer + Index * SizeOf(RGB)
ResultRGB\R - *RGBPointer\R
ResultRGB\G - *RGBPointer\G
ResultRGB\B - *RGBPointer\B
EndIf
Factor = 1.0 / (Width * Height)
ProcedureReturn RGB(ResultRGB\R * Factor, ResultRGB\G * Factor, ResultRGB\B * Factor)
EndProcedure
Procedure.i CompareRecursive(*Image1.IntegralImage, OffX1.i, OffY1.i, *Image2.IntegralImage, OffX2.i = -1, OffY2.i = -1, Width.i = -1, Height.i = -1)
Protected NewSize.i
If Width = -1
Width = *Image2\Width
EndIf
If Height = -1
Height = *Image2\Height
EndIf
If OffX2 = -1
OffX2 = 0
EndIf
If OffY2 = -1
OffY2 = 0
EndIf
If GetMeanColor(*Image1, OffX1, OffY1, Width, Height) = GetMeanColor(*Image2, OffX2, OffY2, Width, Height)
If Width >= Height
If Width >= 2
NewSize = Width >> 1
If Not (CompareRecursive(*Image1, OffX1, OffY1, *Image2, OffX2, OffY2, NewSize, Height) And CompareRecursive(*Image1, OffX1 + NewSize, OffY1, *Image2, OffX2 + NewSize, OffY2, NewSize + (Width & $01), Height))
ProcedureReturn #False
EndIf
EndIf
Else
If Height >= 2
NewSize = Height >> 1
If Not (CompareRecursive(*Image1, OffX1, OffY1, *Image2, OffX2, OffY2, Width, NewSize) And CompareRecursive(*Image1, OffX1, OffY1 + NewSize, *Image2, OffX2, OffY2 + NewSize, Width, NewSize + (Height & $01)))
ProcedureReturn #False
EndIf
EndIf
EndIf
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Structure Position
X.i
Y.i
EndStructure
Define Image.IntegralImage
Define ImageSearch.IntegralImage
UsePNGImageDecoder()
UsePNGImageEncoder()
LoadImage(0, "test.png")
LoadImage(1, "testsearch.png")
IntegralImage(1, @ImageSearch)
Define X.i, Y.i
Define Time.i
NewList FoundEntries.Position()
Time = ElapsedMilliseconds()
IntegralImage(0, @Image)
For X = 0 To Image\Width - ImageSearch\Width
For Y = 0 To Image\Height - ImageSearch\Height
If CompareRecursive(@Image, X, Y, @ImageSearch)
AddElement(FoundEntries())
FoundEntries()\X = X
FoundEntries()\Y = Y
EndIf
Next Y
Next X
Time = ElapsedMilliseconds() - Time
ToPBImage(@Image, 2)
SaveImage(2, "integral.png", #PB_ImagePlugin_PNG)
FreeImage(2)
ToPBImage(@ImageSearch, 2)
SaveImage(2, "integralsearch.png", #PB_ImagePlugin_PNG)
FreeImage(2)
Define Text.s = ""
ForEach FoundEntries()
Text + RSet(Str(FoundEntries()\X), 3, " ") + ", " + RSet(Str(FoundEntries()\Y), 3, " ") + #CRLF$
Next
MessageRequester("Done", "Time needed: " + Str(Time) + "ms" + #CRLF$ + "Found positions: " + #CRLF$ + Text)