【问题标题】:How to add a scalebar without displaying the image in dm-script如何添加比例尺而不在 dm-script 中显示图像
【发布时间】:2021-01-19 11:18:12
【问题描述】:

如何在不显示图像的情况下向图像添加注释,尤其是比例尺?


我有一个记录图像的应用程序。我想为每个重新录制的图像添加一个比例尺。但用户可以选择不显示录制的图像。这就是为什么我想在显示图像之前添加比例尺,并且独立于显示图像。

文档建议使用ImageDocumentSaveToFile() 进行保存。因此,我正在为图像创建一个图像文档。由于将比例尺添加到图像显示中,因此我还添加了图像显示(如果没有给出显示)。但是当我保存图像文档并再次加载时,出现以下错误:

这告诉我在某处我将图像两次添加到图像文档中。但我不知道在哪里(代码贴在下面)。

我可以从保存的路径手动打开图像。图像显示内容(此处为纯色),但不显示比例尺(如上图所示)。所以我想我以某种方式添加了两个显示或图像,其中一个包含比例尺,另一个不包含。但是我现在不知道该怎么做,怎么解决这个问题。

我的精简代码发布在下面。


所以我的问题是:我的代码中的什么导致比例尺不显示以及导致 GMS 在打开图像时引发错误的原因?或者更好的是,向图像添加注释而不显示它们的最佳做法是什么?


number image_width = 128;
number image_height = 128;
image img := RealImage("Image",  4, image_width, image_height);
img = 128;

ImageDocument doc = img.ImageGetOrCreateImageDocument();

void addScalebar(ImageDisplay display){
    number top = image_height - image_height / 5;
    number bottom = image_height;
    number left = 0;
    number right = image_width / 3;
    Component scalebar = NewComponent(31, top, left, bottom, right);
    scalebar.ComponentSetForegroundColor(0, 255, 0);
    display.ComponentAddChildAtBeginning(scalebar);
}

image tmp_img;
for(number i = 0; i < doc.ImageDocumentCountImages(); i++){
    tmp_img = doc.ImageDocumentGetImage(i);
    
    if(tmp_img.ImageCountImageDisplays() > 0){
        for(number j = 0; j < tmp_img.ImageCountImageDisplays(); j++){
            addScalebar(tmp_img.ImageGetImageDisplay(j));
        }
    }
    else{
        ImageDisplay disp = doc.ImageDocumentAddImageDisplay(tmp_img, -2);
        addScalebar(disp);
    }
}

string save_format = "Gatan Format";
string path = PathConcatenate(GetApplicationDirectory("temporary", 1), "demo-image");
doc.ImageDocumentSaveToFile(save_format, path);

string open_path;
ImageDocumentAdjustFileNameForSaveFormat(save_format, path, open_path);
result("Demo image is located at '" + open_path + "'\n");

image display_image := OpenImage(open_path);
display_image.ShowImage();

贴出的代码写在dm-script。我的原始代码是用 python 编写的,这是对dm-script 的直接翻译,对于 可能更容易理解。另外,我觉得在dm-script 中发布问题更“笼统”。该问题适用于两种编程语言,我希望该解决方案也适用。如果没有,如果你知道 python 实现,我也很高兴看到它。

【问题讨论】:

  • 感谢您将其发布为“dm-script”,因为它确实更容易在这里看到。 (该解决方案也适用于 Python。)

标签: dm-script annotations dm-script


【解决方案1】:

非常好的脚本。 您陷入了典型的DM 初学者陷阱,不幸的是,脚本语言的语法非常不标准。

两者之间有区别:

tmp_img = doc.ImageDocumentGetImage(i);

和:

tmp_img := doc.ImageDocumentGetImage(i);

第二个示例是您想要做的:让图像变量tmp_img 指向 imageDocument 的第 i 个图像。

然而,第一个示例将第 i 个图像的数据值复制到一个新创建的图像中。这个新创建的图像没有 imageDisplay!这就是为什么您的代码示例分支到“else”语句的原因。

另请注意,如果您事先修复该行,则不需要 if/else。 ImageDocuments 不能保存图像,它们保存 imageDisplays(与图像相关联)。 更具体地说:ImageDocuments 有一个根组件,与所有组件一样,它可以有子组件。 ImageDisplays 也是组件。

【讨论】:

  • 这是我的问题的答案。由于 python 不知道引用,它仍然使 python 实现变得更糟。我会尽力而为,但除了代码是 python 之外,我可能会打开另一个内容完全相同的问题。当我知道dm-script 解决方案时,我想我可以解决它:(
  • 我已经尝试过“oneliner”image_document.GetRootComponent().GetNthChildOfType(20, 0).AddNewComponent(31, top, left, bottom, right),但不幸的是这不起作用。 dm-script python 模块内可能有一个引用中断或其他东西。
【解决方案2】:

这是问题的 Python 变体的答案。 以下可以做你想做的事(在 Python 中):

import numpy as np
imgArray = np.arange(200000).reshape(400, 500).copy(order='C')
testImg = DM.CreateImage(imgArray)

doc = testImg.GetOrCreateImageDocument()
doc.GetRootComponent().GetNthChildOfType(20, 0).AddNewComponent(31, 10,10,40,400)

path = 'C:/temp/uniqueName3.dm4'
doc.SaveToFile('Gatan Format',path)


# Cleanup 
del testImg
del doc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    • 2013-07-25
    相关资源
    最近更新 更多