65.9K
CodeProject 正在变化。 阅读更多。
Home

智能图像查看的Web系统:上传、深度缩放、标记和注释

starIconstarIconstarIconstarIconstarIcon

5.00/5 (24投票s)

2016年12月1日

CPOL

17分钟阅读

viewsIcon

36086

downloadIcon

632

用于大型图像智能查看、标记和注释的软件

目录

图1. 系统结构。

简介

在许多现代应用程序中,都需要轻松高效地处理高分辨率的大型图像。用户需要工具来加载和查看这些图像,实现流畅的缩放和平移功能,而无需加载时间和延迟,同时还能标记和注释图像的特定区域。最好是将这些工具作为平台无关的Web应用程序提供,以便在用户计算机/设备上实现零足迹。为了满足这一需求,Seadragon Software团队在Microsoft内部开发了一项名为Deep Zoom (DZ) [1] 的技术。DZ随Microsoft Silverlight一起发布,用于Silverlight Multiscale Image控件。它在Web应用程序中效果很好,但需要浏览器支持Silverlight [3]。Open Seadragon (OSD) 项目[4]提供了类似的框架无关的、完全开源的功能。本工作提出了一个基于OSD DZ技术用于大型图像查看的Web软件。

OSD提供了JavaScript (JS) 可用的开发者API [5],可在Web浏览器中使用。此API还支持用于标记的覆盖机制 [6]。OSD覆盖使用放置在图像选定区域之上的“飞入”HTML元素。然而,这种方法似乎不太适合在线标记,特别是对于形状不规则的区域。因此,本工作实现了一种不同的标记和注释技术,该技术基于在Canvas上直接绘制,而不是使用HTML元素。系统结构如图1所示。下面表格列出了所呈现软件的组件。

表. 软件组件。

组件 (Component) 描述 工具
图像上传服务器 将图像上传到文件存储并启动图像处理器以制作图像瓦片金字塔 node.js, JavaScript
上传页面 一个简单的Web页面,由图像上传服务器支持,提供上传UI HTML
图像处理器 从原始图像创建图像瓦片金字塔的组件 .NET Core DLL(目前仅在Windows上运行)
图像查看服务器 支持查看Web应用程序 node.js, JavaScript
查看Web应用程序 用于图像查看、标记和注释的Web应用程序 HTML, CSS, JavaScript, TypeScript

功能

系统工作流程如下。当用户希望上传图像时,他/她会访问*https://UploadServerURL:15005*,并获得一个非常简单的图像上传页面。然后,用户找到所需的图像,并通过按“上传”按钮将图像发布到上传服务器。上传服务器接受上传的文件,将其放置在文件存储中,并在单独的进程中运行图像处理器。图像处理器*dzPyramidBuilder.dll*是一个.NET Core DLL。其任务是从原始图像创建图像瓦片金字塔。图像金字塔创建完成后,图像即可由查看子系统进行DZ查看和注释。

要查看和可能注释图像,用户应该访问*https://ViewingServerURL:15000*,这将显示如图2a和2b所示的页面。

图2a. 图像查看器处于查看模式。

图2b. 图像查看器处于查看模式(片段)。

查看器最初以查看模式打开(图2a和2b)。在此模式下,查看器的工具栏包括一个可供查看的图像下拉列表,后面是“布局”和“编辑”切换按钮。当查看器页面加载时,它会向查看服务器请求可供查看的图像列表。在我们的代码示例中,为了简单起见,假设上传服务器、图像瓦片金字塔文件存储和查看服务器都位于同一台机器上。因此,为了向客户端提供所需的列表,查看服务器会检索包含所有可用图像金字塔的已知文件夹中的子文件夹名称。Web查看器应用程序收到此列表后,会将其放置到客户端工具栏的下拉列表中。用户从下拉列表中选择一个图像名称,并查看图像及其注释(如果有)。图像注释放置在一个侧边面板中,该面板位于图像面板的左侧或右侧。面板位置可以通过“布局”切换按钮进行切换。

在查看模式下工作时,用户可以缩放和平移选定的图像,并查看已标记的选定区域及其注释。我们选择的区域与本地OSD覆盖不同。根据OSD文档[6],覆盖由HTML对象组成,而我们选择的区域只是绘制在OSD查看器画布上。这种方法似乎更灵活,允许用户定义非矩形选定区域并动态管理它们,如下文所示。当用户缩放和平移图像时,选定区域会相应地移动,就像OSD覆盖一样粘附在图像上。在我们的示例中,选定区域可以有三种类型:矩形、圆形和多边形。当用户将鼠标指针悬停在图像中的选定区域上时,动态工具提示会显示选定区域的标题。为了方便管理,选定区域被分组到图层中。属于同一图层的所有选定区域都可以单独显示/隐藏,或者通过切换整个图层来显示/隐藏。此外,选定区域的注释也可以以类似的方式展开/折叠。

通过单击“编辑”切换按钮,用户可以将查看器从查看模式切换到编辑模式。在编辑模式下,图像被冻结在其当前状态(无法移动、缩放或平移),用户可以编辑图像。工具栏(图3)和注释表(annotation table)中会出现新的工具。

图3. 编辑模式下的图像查看器工具栏(带有棋盘格旗帜,指示新图像可用)。

现在,您可以编辑已有的选定区域(更改其标题、注释和图层内的z顺序),或者创建一个新的选定区域,可能还会创建一个新图层。编辑完成后,如果用户满意,可以保存结果。或者,用户也可以撤销编辑到上次保存的状态。

为了创建新的选定区域,用户应从“类型”下拉列表中选择其类型(可以是矩形、圆形或多边形),使用颜色拾取器控件选择边框和背景颜色,定义边框厚度(0到9像素),然后通过在图像上单击鼠标来实际标记选定区域。对于矩形和圆形,只需单击两次即可定义选定区域(矩形的对角点,圆的中心点和定义半径的点)。多边形用户可以定义任意数量的点,最后通过单击工具箱上的相应按钮关闭多边形。选定区域形状创建后,会出现一个模态窗口来定义其文本信息(如图4所示;在单击注释表中相应条目旁的适当切换按钮后,此窗口也用于编辑已存在的选定区域)。通过此模态窗口,可以将一个图层(无论是已有的还是新创建的)分配给选定区域。

图4. 编辑选定区域的模态窗口。

注释表包含可视化工具(图5),用于显示/隐藏选定区域或整个图层,更改选定区域在其图层内的z顺序,编辑文本信息(通过打开编辑模态窗口),或者直接删除选定区域(如果图层不包含任何选定区域,也可以删除图层)。

图5. 注释表中的编辑工具。

现在我们熟悉了功能,让我们简要看一下代码。

代码描述

软件结构如图1所示的流程图。它由图像上传和图像查看子系统组成。

上传

上传子系统包括上传服务器dzImageUpload、简单的Web页面*./dzImageUpload/index.html*以及用于构建DZ图像金字塔的处理器dzImagePyramidBuilderdzImageUpload Web服务器是用JS编写的,通过node.js和expressmulter包运行。服务器监听端口*15005*,支持HTTPS GETPOST请求。当用户浏览URL*https://UploadServerURL:15005*时,上传服务器会响应一个简单的上传页面*./dzImageUpload/index.html*。通过此页面,用户选择图像文件并将其上传到服务器。上传通过HTTPS POST执行。服务器的POST处理程序执行以下任务:

  • 为下一次上传将*./dzImageUpload/index.html*页面重新加载到浏览器,
  • 使用multer包将上传的文件保存到磁盘,
  • 运行dzImagePyramidBuilder为上传的图像准备瓦片金字塔(此操作目前仅在Windows操作系统上可用 - 请参阅下面的解释),最后
  • 通知查看服务器dzImageView,新图像已准备好进行查看和注释。

为此,dzImageUpload充当dzImageView的客户端,使用函数

var req = https.request(options, function (res) {
               //.....
          });

使用参数

var agentOptions = {
    host: 'localhost',
    port: 15000,
    path: '/',
    rejectUnauthorized: false
};

var options = {
    url: 'https://:15000',
    agent: new https.Agent(agentOptions),
    method: 'GET'
};

由于我们假设样本的所有组件都运行在同一台机器上,因此可以使用*localhost* IP地址进行服务器间通信。

dzImagePyramidBuilder组件是从[3]改编的图像金字塔构建器,并转换为.NET Core。在我们的示例中,它被用作一个黑盒,因此其描述超出了本文的范围。有关此组件结构的解释可以在[3]中找到,所用算法在[1]和关于DZ成像的作品中进行了解释。该组件被转换为.NET Core是为了使其与不同的操作系统兼容。但这变得有问题。问题在于dzImagePyramidBuilder使用了System.Drawing程序集,而.NET Core目前不支持它。因此,选择了第三方包CoreCompat.System.Drawing[7]作为替代。它在Windows上运行良好,但在Linux上部署时失败,原因是库内部使用的GDI+缺乏Linux的现成支持。因此,尽管图像上传在Linux上运行良好,但在我们的Linux示例中无法从上传的文件准备金字塔。由于本文的重点是DZ图像查看和注释,因此我允许自己不深入研究Linux中的GDI+支持(您的建议非常受欢迎!)。OSD在其专用页面[8]中也推荐了几个Linux兼容的图像金字塔构建器。我相信Microsoft将在.NET Core的未来版本中为其System.Drawing程序集,特别是Bitmap类型提供支持。

查看、标记和注释

查看子系统是代码示例的主要部分。它包括一个用JS编写的node.js Web服务器dzImageView(使用*express*包)和*./dzImageView/dzweb* Web单页应用程序(SPA),该应用程序用JS和部分TypeScript(TS)编写。

dzImageView Web服务器监听端口*15000*。当用户浏览URL*https://ViewingServerURL:15000*时,服务器会发送*./dzImageView/dzweb/index.html*页面,启动dzweb Web应用程序。该应用程序可以运行两个参数,即:

  • lang=xx - UI的语言,其中“xx”代表语言的两个首字母,例如,“en”代表英语(这是默认值),以及
  • layout=x - 表示图像和注释面板的相互放置。默认情况下,注释面板位于图像面板的右侧。如果layout参数设置为“l”或“L”,则注释面板位于图像面板的左侧。

因此,URL

https://ViewingServerURL:15000?lang=ru&layout=l

将导致查看器使用俄语UI,注释位于浏览器窗口的左侧。

dzweb主要使用纯JS和CSS开发。标准和第三方包仅用于WebSocket通信(socket.io)、选定区域颜色拾取器(jcolor)以及当然还有DZ本身(openseadragon)。TS用于在*./dzImageView/dzweb/ts*文件夹中描述的以下文件中定义的选定区域类型:基础类型在*selectedRegion.ts*中,派生类型在*selectedRegionCircle.ts*、*selectedRegionPolygon.ts*和*selectedRegionRectangle.ts*中。TS文件应作为系统准备的一部分离线转换为JS。这可以通过*tsc.exe*转译器(必须安装)从*./dzImageView/dzweb/ts*文件夹执行以下命令完成:

"C:\Program Files (x86)\Microsoft SDKs\TypeScript\2.0"\tsc.exe

该命令使用*tsconfig.json*文件。为了方便用户,上述命令已放置在命令文件*tsc.cmd*中。根据参数*“compilerOptions”*.*“outDir”*,其输出将放入*./dzImageView/dzweb/js/selectedRegion*文件夹。

我们的Web应用程序的大部分位于*./dzImageView/dzweb/js*文件夹中。我们已经熟悉了包含TS转译结果文件的selectedRegion子文件夹。dzweb应用程序设计时严格区分HTML元素和业务逻辑。处理HTML元素的文件放置在单独的*page*子文件夹中,并命名为*page*.js。与HTML标签无关的代码文件位于*./dzImageView/dzweb/js*文件夹中。Page*()函数由非页面代码直接调用。反向调用通过提供给*page*代码的适当回调函数执行。

让我们简要看一下dzweb代码。代码执行从*global.js*文件中的函数startUp()开始。它从HTML页面调用:

<script src="js/mainDz.js" onload="startUp()"></script>

函数startUp()激活theSingleton对象(*singleton.js*文件)。theSingleton对象用于保存跨应用程序使用的变量,从而避免全局变量。在startUp()中,theSingleton启动与服务器的WebSocket通信,并使用‘init’消息请求有关可用图像的信息。通过WebSocket与服务器通信在函数exchangeWithServer()中使用Promise实现异步操作。它接收消息名称、要发送到服务器的对象以及用于处理服务器响应的回调函数作为参数。当Web应用程序从服务器接收到可用图像列表时,它会创建一个PageInfo对象(*./dzImageView/dzweb/js/page/page.js*文件),通过new方法,将图像列表和用于获取图像详细数据的回调函数getImageInfo()作为参数传递给PageInit()。当服务器收到第一张图像的详细信息后,dzweb完成初始化,并显示第一张图像及其标记和注释(如果有)。主要功能按文件描述如下:

  • *global.js*为整个应用程序提供全局函数。它还包含常量
    const hostIPAddress = '$0';
    const __isRightLayout = $1;

    其中美元符号开头的占位符将被服务器替换为从客户端请求中获取的实际值。这对于hostIPAddress参数尤其重要,因为它为Web应用程序提供了正确的服务器IP地址。

  • *mainDz.js*包含大多数OSD相关代码和WebSocket消息处理程序。
  • *layerCollection.js*和*layer.js*分别包含处理图层和选定区域集合的LayerCollectionLayer对象。
  • *transform.js*用于负责Web到图像坐标和反之坐标转换的Transform对象。
  • *tip.js*包含在鼠标悬停在图像选定区域上时用于绘制工具提示的Tip对象。
  • 有一些值得提及的特性。

将选定区域粘附到图像上

移动选定区域(“粘附”)主要通过两段代码实现。以下处理程序附加到OSD viewer对象的update-viewport事件(*mainDz.js*文件)。

viewer.addHandler('update-viewport', function () {
    loopThroughAllSelectedRegions(function (selectedRegion) {
        selectedRegion.draw(viewer);
    });
});

函数selectedRegion.draw(viewer)由基类SelectedRegion实现。此函数调用派生选定区域类型实现的函数public drawInternal(vr: any, ctx: any)drawInternal()包括以下点坐标转换:

Transform.prototype.imageToWeb = function (viewer, imagePoint) {
    var vpt = viewer.viewport;
    var ptWeb = vpt.pixelFromPoint(vpt.imageToViewportCoordinates(imagePoint), 
		    	    true); //!
			
    return osdPoint(ptWeb.x, ptWeb.y);
}

viewer.viewport函数的第二个参数应设置为true,表示当前点的位置。

图标字体 Font Awesome

该字形字体[9]用于装饰可视化工具,特别是按钮。在本示例中,仅使用*fontawesome-webfont.ttf*字体文件。扩展名为*woff*和*woff2*的字体文件已从安装中删除,查看服务器在尝试下载它们时会报告错误。这些错误消息可以忽略。

本地化

如上所述,用户可以指定参数lang=xx来定义UI语言。查看服务器会将*./dzImageView/dzweb/settings/settings_xx.js*文件作为查看Web应用程序的一部分下载。默认情况下,使用英语文件。为简单起见,设置文件目前包含Web应用程序所需的所有设置(例如,工具提示的颜色)。目前,除了英语文件外,还提供了俄语设置文件以供测试。

互斥编辑

当用户开始编辑特定图像时,其他用户不允许编辑此图像(此图像的工具栏中“编辑”切换按钮消失),直到“锁定”该图像的用户放弃该图像的编辑模式。如果用户编辑器保存了编辑结果,服务器会更新当前查看该图像的客户端。用户编辑器可能会在编辑模式下关闭Web应用程序。这可能导致图像编辑被“锁定”直到服务器重启。为了避免此问题并“解锁”图像,允许其他用户编辑它,查看服务器会定期(周期由常量socketsCheckTimeoutInSec定义,当前设置为10秒)并在新客户端连接时,检查所有客户端连接的有效性,删除无效连接,并解锁由未连接客户端编辑的图像。请注意,这只是一个示例,实际系统应具有某种权限机制来进行编辑和更新。

新图像可用性通知

当新图像被处理成瓦片金字塔并准备好查看时,服务器会向所有运行的客户端发送通知。工具栏右侧的棋盘格旗帜标志表示新图像可用,将在下次重新加载Web页面时包含在图像列表中。

运行示例

运行上传和查看服务器都需要安装Node.js。

Windows

为了运行上传子系统,需要安装.NET Core来运行dzImagePyramidBuilder组件。本示例使用.NET Core版本1.0.0进行测试。查看子系统没有先决条件。操作步骤如下:

  1. 将文件解压到某个根文件夹。
  2. 转到文件夹*./dzImagePyramidBuilder/src/dzImagePyramidBuilder*并运行文件*publish.cmd*,其中包含以下命令:
    dotnet publish -o ../../../dzImageUpload/pyramidBuilder -c Release

    它将构建dzImagePyramidBuilder并将其发布到*./dzImageUpload/pyramidBuilder*文件夹。

  3. 可选步骤。转到文件夹*./dzNodeServer/dzweb/ts*并运行*tsc.cmd*命令文件,其中包含命令
    "C:/Program Files (x86)/Microsoft SDKs/TypeScript/2.0"/tsc.exe

    将TS文件从该文件夹转译到*./dzNodeServer/dzweb/js/selectedRegion*文件夹。实际上,这些JS文件已经到位。

    注意:如果您更改TS文件,请不要忘记转译TS文件。

  4. 从根文件夹运行*Upload.cmd*命令文件。它以以下命令启动dzImageUpload服务器:
    node server

    命令来自*./dzImageUpload*文件夹。

    注意:上述命令在Windows和Linux环境中都运行上传和查看服务器。

  5. 打开Web浏览器(建议使用Google Chrome),浏览URL*https://:15005*并上传您选择的图像文件。图像将被放置在*./dzImageUpload/uploads*文件夹中,将空格替换为下划线,并添加刻度时间到其名称。图像瓦片金字塔将输出到*./dzImageView/dzweb/images*下的相应子文件夹。
  6. 从根文件夹运行*View.cmd*命令文件。它从*./dzImageView*文件夹启动dzImageView服务器。
  7. 浏览URL*https://:15000* [可选扩展:?lang=en&layout=l],其中en可以替换为ru以显示俄语UI,或者替换为您喜欢的语言准备的文件。查看器Web应用程序屏幕如图2a和2b所示,显示您上传的图像。要进行编辑,请单击“编辑”切换按钮。编辑完成后,通过按“保存”按钮保存结果,然后再次单击“编辑”切换按钮退出编辑模式。

    可以通过打开Microsoft Visual Studio 2015的*./dz.sln*解决方案来调试服务器和金字塔构建器。

Linux

如前所述,当前版本的金字塔构建器无法在Linux上运行。因此,尽管图像上传运行良好,但在Linux上运行上传子系统没有意义。因此,仅讨论查看子系统。使用的版本是Ubuntu 16.04。

在此,我描述了在Windows中安装后(在前一节中描述)在Linux中执行的必要步骤。

  1. 将Windows根文件夹复制到Linux中相应的根文件夹(实际上只需要将*dzImageView*子文件夹复制到根文件夹)。
  2. 将已在Windows中准备好的图像金字塔复制到*./dzImageView/dzweb/images*文件夹。
  3. 运行dzImageView服务器。
  4. 按照Windows安装第7点中的描述查看/编辑图像。

进一步开发

如我上面所写,此软件不能被视为一个成熟的产品。因此,各种错误(例如,当前的圆形选定区域可能会占用图像外部的空间)非常可能存在。当然,UI改进的空间是无限的。可以添加具有平滑边界(可能是贝塞尔曲线)的选定区域。开发人员API将特别有用,可以为与选定区域相关的事件(如单击、悬停等)分配自定义处理程序。当前版本在Google Chrome和Mozilla Firefox中运行良好。在Microsoft浏览器(Internet Explorer和Edge)中,工具提示机制应该得到修复。布局可以适应移动设备。

结论

本工作提出了用于大型图像智能查看、标记和注释的软件。Deep Zoom技术用于在没有延迟和滞后的情况下查看高分辨率的大型图像。上传和查看服务器均使用Node.js和JavaScript开发,因此具有平台独立性。Deep Zoom技术涉及使用图像瓦片金字塔。为了准备这些金字塔,使用了单独的组件(其当前版本由于Linux缺乏现成的GDI+支持而只能在Windows上运行)。图像查看Web应用程序使用HTML/CSS、JavaScript和TypeScript开发,仅使用了最少的第三方包。

参考文献

历史

  • 2016年12月1日:初始版本
© . All rights reserved.