Dm script 查找模式图像(二进制文件)

Dm script 查找模式图像(二进制文件),dm-script,pattern-finding,Dm Script,Pattern Finding,对于数字显微照片中的字符串变量,我们可以使用“查找”功能找到特定图案的位置: Number find( String str, String sub_str ) 我想做同样的,但与图像数据。例如,我可以用 image img := exprsize(1024, icol); 我想找到的模式是 image pattern := exprsize( 15, icol+64 ); 在上述情况下,我们知道模式w.r.t的偏移量。数据位于第64列。在实际案例中,我们不会有如此简单的模式(即直线)。使

对于数字显微照片中的字符串变量,我们可以使用“查找”功能找到特定图案的位置:

Number find( String str, String sub_str )
我想做同样的,但与图像数据。例如,我可以用

image img := exprsize(1024, icol);
我想找到的模式是

image pattern := exprsize( 15, icol+64 );
在上述情况下,我们知道模式w.r.t的偏移量。数据位于第64列。在实际案例中,我们不会有如此简单的模式(即直线)。使用“for”循环的残酷强制方法肯定会奏效,但当数据量越来越大时,速度会变得非常缓慢。有人有更好/优雅的建议吗?1D图像可能更容易,2D图像如何


非常感谢

如果您正在有效地寻找与数字数据的精确匹配,那么明智地使用图像表达式可能是找到解决方案的最有效途径。大致按照您的示例,我们首先设置源数据和目标模式:

Image sourceData := RealImage("Source data", 4, 4096);
sourceData = Random();

Image targetPattern := RealImage("Target pattern", 4, 15);
targetPattern = sourceData.Index(icol + 1733, 0);
然后,我们用一个图像表达式准备一个精心安排的搜索缓冲区:

Number targetSize = targetPattern.ImageGetDimensionSize(0);
Number searchBufferW = sourceData.ImageGetDimensionSize(0) - targetSize;
Image searchBuffer := RealImage("Search buffer", 4, searchBufferW, targetSize);
searchBuffer = sourceData.Index(icol + irow, 0);
这将在2D图像的垂直列中排列源数据的所有潜在匹配子集。最后,我们做一点图像数学来定位与目标模式的匹配(如果存在):

searchBuffer = Abs(searchBuffer - targetPattern.Index(irow, 0));
Image projectionVector := targetPattern.ImageClone();
projectionVector = 1.0;
Image searchResult := projectionVector.MatrixMultiply(searchBuffer);

Number posX, posY;
Number wasFound = (searchResult.Min(posX, posY) == 0);
String resultMsg = (wasFound) ? "Pattern found at " + posX : "Pattern not found";
OKDialog(resultMsg);
第一行将在搜索缓冲区列中与目标模式匹配的每个像素中产生精确的零。垂直求和搜索缓冲区,并使用Min()函数查找零,可以加快搜索匹配项的速度

注意使用MatrixMultiply()进行快速垂直和投影。这仅适用于Real类型(4字节浮点)源数据。然而,有一些稍微复杂一些的快速数据投影方法,对于任何数字数据类型也会给出相当快的结果


尽管针对一维数据集中的一维模式进行了说明,但通过使用多维搜索缓冲区和使用ImageDataSlice对象的更高级索引,该方法可能可以扩展到二维和三维数据集中的一维和二维模式,但这将是另一个问题的主题。

鉴于您正在有效地寻找与数字数据的精确匹配,那么明智地使用图像表达式可能是找到解决方案的最有效途径。大致按照您的示例,我们首先设置源数据和目标模式:

Image sourceData := RealImage("Source data", 4, 4096);
sourceData = Random();

Image targetPattern := RealImage("Target pattern", 4, 15);
targetPattern = sourceData.Index(icol + 1733, 0);
然后,我们用一个图像表达式准备一个精心安排的搜索缓冲区:

Number targetSize = targetPattern.ImageGetDimensionSize(0);
Number searchBufferW = sourceData.ImageGetDimensionSize(0) - targetSize;
Image searchBuffer := RealImage("Search buffer", 4, searchBufferW, targetSize);
searchBuffer = sourceData.Index(icol + irow, 0);
这将在2D图像的垂直列中排列源数据的所有潜在匹配子集。最后,我们做一点图像数学来定位与目标模式的匹配(如果存在):

searchBuffer = Abs(searchBuffer - targetPattern.Index(irow, 0));
Image projectionVector := targetPattern.ImageClone();
projectionVector = 1.0;
Image searchResult := projectionVector.MatrixMultiply(searchBuffer);

Number posX, posY;
Number wasFound = (searchResult.Min(posX, posY) == 0);
String resultMsg = (wasFound) ? "Pattern found at " + posX : "Pattern not found";
OKDialog(resultMsg);
第一行将在搜索缓冲区列中与目标模式匹配的每个像素中产生精确的零。垂直求和搜索缓冲区,并使用Min()函数查找零,可以加快搜索匹配项的速度

注意使用MatrixMultiply()进行快速垂直和投影。这仅适用于Real类型(4字节浮点)源数据。然而,有一些稍微复杂一些的快速数据投影方法,对于任何数字数据类型也会给出相当快的结果


尽管针对一维数据集中的一维模式进行了说明,但通过使用多维搜索缓冲区和使用ImageDataSlice对象的更高级索引,这种方法可能可以扩展到二维和三维数据集中的一维和二维模式,但这将是另一个问题的主题。

正如Mike所指出的,互相关是在存在噪声的情况下搜索模式的一种好方法。但是,在没有噪音的情况下搜索更好(如果不是完美的方法的话)!这将在1D和2D中用于脚本编写。见下文

number sx = 1024
number sy = 1024
number pw = 32
number ph = 32
number px = 100 // trunc( random()*(sx-pw) )
number py = 200 // trunc( random()*(sy-ph) )

image test := RealImage("Data",4,sx,sy)
test = random()
image pattern := test[py,px,py+ph,px+pw].ImageClone()
//test.showimage()
//pattern.showimage()
image patternSearch = test*0
patternSearch[0,0,ph,pw] = pattern
//patternSearch.ShowImage()

image corr := CrossCorrelate(test,patternSearch)
corr.ShowImage()
number mx,my,mv
mv = max(corr,mx,my)
mx -= trunc(sx/2)       // because we've placed the pattern in the 
my -= trunc(sy/2)       // top/left of the search-mask
Result("\n Pattern = " + px + " / " + py )
Result("\n max = " + mv + " at " + mx + "/" + my )

image found = test*0
found[my,mx,my+ph,mx+pw]=pattern
rgbImage overlay = RGB((test-found)*256,found*256,0)
overlay.ShowImage()
如果您的问题只有1D,并且您拥有非常大的数据,那么另一种方法可能会为您提供更快的解决方案。然后,我建议尝试使用原始数据流(通过TagGroup流命令),并使用调整搜索所需的任何附加信息,即仅搜索流中某个模式的开头,然后仅验证“点击”等

此处添加的注释旨在解决1D图像中的搜索模式问题。如果我们运行以下脚本几次,那么我们会发现大约有50%的时间无法正确找到模式

number sx = 1024
number sy = 0
number pw = 16
number ph = 0
number px = trunc( random()*(sx-pw) )
number py = 0 // trunc( random()*(sy-ph) )

image test := RealImage("Data",4,sx );
test = random();
image patternSearch := exprsize( sx, icol<pw? test[icol+px, irow]: 0 );
// test.ShowImage();
// patternSearch.ShowImage();
patternSearch.SetName( "PatternSearch" );
//

image corr := CrossCorrelate(test,patternSearch)
// corr.ShowImage()
number mx,my,mv
mv = max(corr,mx,my)
mx -= trunc(sx/2)       // because we've placed the pattern in the 
my -= trunc(sy/2)       // top/left of the search-mask
if( mx <= 0 ) mx += sx;
Result("\n\n Pattern = " + px + " / " + py )
Result("\n max = " + mv + " at " + mx + "/" + my )
编号sx=1024
数字sy=0
数字pw=16
数字ph=0
数字px=trunc(random()*(sx pw))
数字py=0//trunc(random()*(sy-ph))
图像测试:=真实图像(“数据”,4,sx);
测试=随机();

image patternSearch:=exprsize(sx,icol正如Mike所指出的,互相关是在有噪声的情况下搜索模式的一种好方法。但是,在没有噪声的情况下搜索模式更好(如果不是完美的方法的话)。这将在1D和2D中用于脚本编写。请参见下文

number sx = 1024
number sy = 1024
number pw = 32
number ph = 32
number px = 100 // trunc( random()*(sx-pw) )
number py = 200 // trunc( random()*(sy-ph) )

image test := RealImage("Data",4,sx,sy)
test = random()
image pattern := test[py,px,py+ph,px+pw].ImageClone()
//test.showimage()
//pattern.showimage()
image patternSearch = test*0
patternSearch[0,0,ph,pw] = pattern
//patternSearch.ShowImage()

image corr := CrossCorrelate(test,patternSearch)
corr.ShowImage()
number mx,my,mv
mv = max(corr,mx,my)
mx -= trunc(sx/2)       // because we've placed the pattern in the 
my -= trunc(sy/2)       // top/left of the search-mask
Result("\n Pattern = " + px + " / " + py )
Result("\n max = " + mv + " at " + mx + "/" + my )

image found = test*0
found[my,mx,my+ph,mx+pw]=pattern
rgbImage overlay = RGB((test-found)*256,found*256,0)
overlay.ShowImage()
如果您的问题只是1D,并且您的数据非常大,那么另一种方法可能会为您提供更快的解决方案。然后,我建议尝试使用原始数据流(通过TagGroup流命令)并使用您必须调整搜索的任何附加信息,即仅搜索流中模式的开头,然后仅验证“命中”等

这里添加的注释是为了解决1D图像中搜索模式的问题。如果我们运行以下脚本几次,我们会发现大约50%的时间无法正确找到模式

number sx = 1024
number sy = 0
number pw = 16
number ph = 0
number px = trunc( random()*(sx-pw) )
number py = 0 // trunc( random()*(sy-ph) )

image test := RealImage("Data",4,sx );
test = random();
image patternSearch := exprsize( sx, icol<pw? test[icol+px, irow]: 0 );
// test.ShowImage();
// patternSearch.ShowImage();
patternSearch.SetName( "PatternSearch" );
//

image corr := CrossCorrelate(test,patternSearch)
// corr.ShowImage()
number mx,my,mv
mv = max(corr,mx,my)
mx -= trunc(sx/2)       // because we've placed the pattern in the 
my -= trunc(sy/2)       // top/left of the search-mask
if( mx <= 0 ) mx += sx;
Result("\n\n Pattern = " + px + " / " + py )
Result("\n max = " + mv + " at " + mx + "/" + my )
编号sx=1024
数字sy=0
数字pw=16
数字ph=0
数字px=trunc(random()*(sx pw))
数字py=0//trunc(random()*(sy-ph))
图像测试:=真实图像(“数据”,4,sx);
测试=随机();

image patternSearch:=exprsize(sx,icol根据要求,这里是一个片段,显示了如何在“原始”数据流中进行搜索。我并不是说下面的脚本是最快或最优雅的解决方案,它只是显示了相应的命令是如何工作的。(您可以在的“文件输入和输出”中找到它们的文档)联机F1帮助的一节。)

我的“想法”是:只需搜索