基本介紹
▶在YouTube上觀看。
Imatest IT(工業測試)是一組應用程式介面(API),可讓開發人員在自己的自訂應用程式中存取 Imatest 強大的影像品質分析工具。
Imatest IT 適用於 64 位元 Windows、macOS 和 Linux 系統,並包含C 、 C++ 、 Python 、 Objective-C、 .NET (僅限 Windows,包括C#和Visual Basic )以及LabVIEW 的函式庫。 IT還包含可從命令列或腳本呼叫的獨立可執行檔。這些 API 庫執行的計算與對應的基於 GUI 的 Imatest Master 模組完全相同。
Imatest IT 是一個完整的軟體包,包括模組庫、支援文件、範例程式碼以及與模組互動的完整應用程式。
儘管 Imatest IT 獨立於 Imatest Master 運行,但我們強烈建議 IT 用戶至少在現場安裝一套 Master 版本。 Imatest Ultimate Edition包含IT和Image Master 版本,並提供大幅折扣,是大多數用戶的理想選擇。正如您將在下面的步驟 2中看到的那樣,使用 Master 可以更輕鬆地設定測試配置(這是任何 IT 應用程式不可或缺的一部分)。
Imatest IT 模組
Imatest IT包含20個影像分析模組:
| SFR - 測量手動指定傾斜邊緣的 MTF 及相關結果 | SFRplus-使用Imatest高度自動化的SFRplus圖表與模組,測量MTF、橫向色差、失真、色調響應等諸多參數。 |
| 星形- 使用西門子星形圖(通常為正弦曲線)測量 MTF 和橫向色差 | Colorcheck-使用24色X-Rite Colorchecker色卡測量色彩準確度、雜訊、色調反應等參數。 |
| 階梯圖- 透過灰階階梯圖測量色調響應、伽瑪值、雜訊等參數 | 楔形曲線-使用雙曲楔形曲線測量MTF,可在ISO 12233:2000和eSFR ISO圖表中找到。 |
| OIS-衡量影像穩定功能的有效性 | 均勻性- 測量平場影像的影像均勻性、色彩漸層以及熱像素/死像素。 |
| 失真度-使用網格或棋盤格圖案測量失真度 | eSFR ISO - 使用增強型 ISO 12233:2014 圖表測量 MTF、色彩準確度、雜訊和色調響應 |
| 瑕疵- 從平場影像測量視覺上明顯的瑕疵 | 點陣圖案- 測量點陣圖案的畸變和橫向色差(符合 I3A CPIQ 標準) |
| 多重測試- 分析各種測試圖表的影像,以評估色彩準確度、色調響應、雜訊、信噪比 (SNR) 和 ISO 感光度。 | 棋盤格測試-使用棋盤格靶紙測量MTF、橫向色差和變形 |
| 隨機模組- 使用散落硬幣或隨機(空間不變)圖表測量紋理質量 | SFRreg - 使用一個或多個自動偵測的 SFRreg 目標測量 MTF 和橫向色差 |
| Log FC-使用對數頻率-對比圖來衡量訊號處理(MTF 作為空間頻率和對比度的函數)的效果 | 任意圖表- 從 Imatest 中其他地方不支援的圖表設計(包括您自己的自訂設計)測量各種影像品質因素。 |
| 雜散光- 分析掃過視野的小型明亮光源的影像,以產生歸一化的度量雜散光影像和相關輸出。 | 同心圓環- 根據 ISO 8600-3 圖表測量視野角。 |

使用 Imatest IT
如圖所示,與 Imatest IT 合作是一個四步驟流程。本文將詳細介紹每個步驟。
第一步:準備測試環境並收集測試目標
輸入:無
輸出:測試影像
Imatest 的分析模組需要構圖正確、光線充足的測試目標影像。測試環境設定完畢後,請拍攝您將使用的模組所需的測試目標影像。
步驟 2:配置包含測試影像的 INI 文件
輸入:測試影像
輸出:INI 文件
使用步驟 1 中擷取的部分測試影像,透過 Imatest Master 分析影像文件,選擇應用程式所需的選項,並設定圖表的興趣區域 (ROI)。一切準備就緒後,匯出 INI 檔案並將其與應用程式原始檔案一起儲存。
在Imatest中,您可以使用Imatest IT 設定視窗中的「儲存 ini 檔案」按鈕,將 ini 檔案儲存為僅包含所需部分的格式。
步驟 3:整合並呼叫 Imatest IT 模組
輸入:測試影像、INI 文件
輸出:分析結果
使用你喜歡的程式語言編寫應用程序,並使用你的圖像和 INI 檔案呼叫模組函數。
步驟四:處理結果
輸入:分析結果
輸出:您需要的任何內容
載入分析結果,並以您想要的方式使用它們。
安裝 Imatest IT
如果您還沒有下載 Imatest IT,您可以在下載頁面進行下載。
接下來,請按照此處的安裝說明進行操作。
Imatest IT 安裝成功後,您需要在電腦上啟動它。請按照以下說明啟動您的節點鎖定或浮動許可證。如果執行 Imatest IT 的電腦沒有網路連接,您也可以選擇離線啟動。
安裝後任務
僅限 Linux 系統 - 更新 LD_LIBRARY_PATH
在 Linux 電腦上,需要將幾個路徑加入LD_LIBRARY_PATH環境變數中。為此,您需要編輯~/.bashrc (或類似檔案),並新增以下幾行。
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/Imatest/v26.1/IT/bin
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/Imatest/v26.1/IT/libs/library/cpp
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024bruntime/glnxa64
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024b/bin/glnxa64
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024b/sys/os/glnxa64
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024b/sys/opengl/lib/glnxa64
有關編輯環境變數的更多信息,請參閱這篇文章。
僅限 macOS - 更新 DYLD_LIBRARY_PATH
在 macOS 電腦上,需要將幾個路徑加入DYLD_LIBRARY_PATH環境變數中,方法是將以下幾行加入 ~/.bash_profile 檔案:
英特爾 macOS:
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/Imatest/IT/v26.1/bin
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/Imatest/IT/v26.1/libs/library/cpp
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/MATLAB/MATLAB_Runtime/R2024b/runtime/maci64
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/MATLAB/MATLAB_Runtime/R2024b/bin/maci64
蘋果晶片 macOS:
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/Imatest/IT/v26.1/bin
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/Imatest/IT/v26.1/libs/library/cpp
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/MATLAB/MATLAB_Runtime/R2024b/runtime/maca64
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/MATLAB/MATLAB_Runtime/R2024b/bin/maca64
僅限 macOS - 設定 MW_OUT_PROCESS
僅在 macOS 系統上,MATLAB Runtime 在某些情況下會在為 Imatest 建立圖表時崩潰。此問題已在 Objective-C 同心圓範例中發現。解決方法是設定以下環境變數(該範例現在會在執行時間自動設定):
export MW_OUT_PROCESS=1
您可以在目前 shell 中暫時設定此值,也可以在 ~/.bash_profile 檔案中設定。
(可選)- 使用 MCR 快取縮短啟動時間
首次使用 Imatest IT 函式庫時,必須將其解壓縮到暫存目錄。根據您的系統配置,這可能需要幾秒鐘。在某些情況下,每次使用可能需要解壓縮,尤其是在使用Imatest IT 採購庫時。
為了防止 Imatest IT 庫被重複解壓縮,您需要設定兩個額外的環境變數: MCR_CACHE_ROOT和MCR_CACHE_SIZE。 MCR_CACHE_ROOT變數告訴Matlab Runtime 要將 Imatest IT 庫解壓縮到哪裡。將其設定為所有使用者都具有寫入權限的特定位置,可確保作業系統在清理臨時檔案時不會刪除此快取。所有使用 Imatest IT 的使用者都必須擁有對該目錄的讀寫權限,否則在 Imatest IT 初始化時可能會出現難以理解的錯誤。 MCR_CACHE_SIZE變數是 Matlab Runtime 快取允許成長的最大大小(以位元組為單位),超過這個大小後,其他函式庫將會被刪除。為了保持 Imatest IT 的最佳效能,該值應至少設定為900000000 ,這將顯著加快部分使用者的 Imatest IT 啟動速度。
請按照此處的說明將這些變數新增到您的環境中。
視窗
| 變數名 | 價值 |
|---|---|
| MCR_CACHE_ROOT | C:\ProgramData\Imatestmcr_cache26.1IT |
| MCR_CACHE_SIZE | 900000000 |
Linux
| 變數名 | 價值 |
|---|---|
| MCR_CACHE_ROOT | /var/lib/imatest/mcr_cache/26.1/IT |
| MCR_CACHE_SIZE | 900000000 |
macOS
| 變數名 | 價值 |
|---|---|
| MCR_CACHE_ROOT | $HOME/imatest/mcr_cache/26.1/IT |
| MCR_CACHE_SIZE | 900000000 |
請注意,對於 macOS 系統,您需要建立此資料夾。
其他安裝步驟
請在下方選擇您偏好的介面,查看詳細說明。
為了使您的應用程式能夠與 Imatest IT C 或 C++ DLL 進行交互,您的系統需要知道在哪裡可以找到它們。
有兩種方法可以讓系統使用 Imatest IT C 或 C++ DLL:
- 將庫目錄加入系統的PATH或LD_LIBRARY_PATH變數中(建議)。
- 將 DLL 檔案複製到與應用程式相同的目錄中。
加入 PATH 或 LD_LIBRARY_PATH 變數中
根據您將使用的介面,將下列目錄新增至系統的PATH (Windows)或LD_LIBRARY_PATH (Linux)變數中。有關如何執行此操作的說明,請參閱“編輯系統環境變數” 。
注意:如果您使用的是 C++ 函式庫,Linux 使用者可能已經按照上面的附加安裝步驟完成了此步驟。
為了使您的應用程式能夠與 Imatest IT C 或 C++ DLL 進行交互,您的系統需要知道在哪裡可以找到它們。
有兩種方法可以讓系統使用 Imatest IT C 或 C++ DLL:
- 將庫目錄加入系統的PATH或LD_LIBRARY_PATH變數中(建議)。
- 將 DLL 檔案複製到與應用程式相同的目錄中。
加入 PATH 或 LD_LIBRARY_PATH 變數中
根據您將使用的介面,將下列目錄新增至系統的PATH (Windows)或LD_LIBRARY_PATH (Linux)變數中。有關如何執行此操作的說明,請參閱“編輯系統環境變數” 。
注意:如果您使用的是 C++ 函式庫,Linux 使用者可能已經按照上面的附加安裝步驟完成了此步驟。
| 作業系統 | 變數名 | 價值 |
|---|---|---|
| 視窗 | 小路 | C:\Program Files\Imatestv26.1\ITlibs\libraryc |
| Linux | LD_LIBRARY_PATH | /usr/local/Imatest/v26.1/IT/libs/library/c |
| 作業系統 | 變數名 | 價值 |
|---|---|---|
| 視窗 | 小路 | C:\Program Files\Imatestv26.1\ITlibs\library\cpp |
| Linux | LD_LIBRARY_PATH | /usr/local/Imatest/v26.1/IT/libs/library/cpp |
| macOS | DYLD_LIBRARY_PATH | /Applications/Imatest/IT/v26.1/libs/library/cpp |
複製 Imatest IT DLL
如果您不想變更PATH或LD_LIBRARY_PATH變量,也可以透過將 Imatest IT DLL 複製到與專案執行檔相同的目錄中來引用它們。
Visual Studio使用者可以透過新增產生後事件來自動執行此程序。
- 在解決方案資源管理器中,以滑鼠右鍵按一下專案並選擇“屬性” 。
- 在「配置屬性」和「生成事件」下,選擇「生成後事件」 。
- 在命令列框中新增以下內容:
copy /Y "C:Program FilesImatestv26.1ITlibslibrarycimatest_library.dll" ";$(TargetDir)"
對專案中的每個配置重複這些步驟。
現在, imatest_library.dll檔案將自動複製到您的專案目標目錄,並且您的應用程式可以載入它。
複製 Imatest IT DLL
如果您不想變更PATH或LD_LIBRARY_PATH變量,也可以透過將 Imatest IT DLL 複製到與專案執行檔相同的目錄中來引用它們。
Visual Studio使用者可以透過新增產生後事件來自動執行此程序。
- 在解決方案資源管理器中,以滑鼠右鍵按一下專案並選擇“屬性” 。
- 在「配置屬性和生成事件」下,選擇「生成後事件」 。
- 在命令列框中新增以下內容:
copy /Y "C:Program FilesImatestv26.1ITlibslibrarycppimatest_library.dll" "$(TargetDir)"
對專案中的每個配置重複這些步驟。
現在, imatest_library.dll檔案將自動複製到您的專案目標目錄,並且您的應用程式可以載入它。
為了讓您的應用程式能夠使用 Objective-C/C++ 與 Imatest IT C++ 庫進行交互,您的系統需要知道在哪裡可以找到它們。
有兩種方法可以讓系統使用 Imatest IT C++ 函式庫:
-
- 將庫目錄加入到系統的DYLD_LIBRARY_PATH變數中。
-
- 將庫檔案複製到與應用程式相同的目錄中。
加到 DYLD_LIBRARY_PATH 變數
根據您將使用的接口,將以下資料夾路徑新增至系統的DYLD_LIBRARY_PATH變數中。有關如何執行此操作的說明,請參閱“編輯系統環境變數” 。
| 作業系統 | 變數名 | 價值 |
|---|---|---|
| macOS | DYLD_LIBRARY_PATH | /Applications/Imatest/IT/v26.1/libs/library/cpp |
| macOS | DYLD_LIBRARY_PATH | /Applications/Imatest/IT/v26.1/bin |
複製 Imatest IT 庫
如果您不想變更DYLD_LIBRARY_PATH變量,也可以透過將 Imatest IT 函式庫複製到與專案執行檔相同的目錄中來引用它們。
Xcode 使用者可以透過新增「複製檔案」和「運行腳本」建置階段來自動化此流程。
-
- 在專案編輯器中,選擇應用程式的目標,然後前往「建置階段」窗格。
-
- 前往編輯器選單,然後選擇「新增建置階段」:「新增複製檔案建置階段」 。
-
- 在複製檔案階段,將目標位置設定為產品目錄。
-
- 點擊“+”圖標,然後點擊“新增其他...”按鈕。
-
- 導覽至 /Applications/Imatest/IT/v26.1/libs/library/cpp/,選擇 libImatest.dylib,按「開啟」 ,然後按「完成」 。
-
- 在「複製檔案」階段,取消選取「複製登入副本」 。
-
- 對 /Applications/Imatest/IT/v26.1/bin/ShaferFilechck.dylib 重複此程序。
-
- 在執行腳本階段新增 install_name_tool -change @loader_path/libImatest.dylib @rpath/libImatest.dylib ${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/MacOS/${TARGETNAME}
The Imatest IT Python Interface is shipped as a Python module. Before referencing it in your scripts, you will need to install it using Python's package manager. This must be done on the command line, and requires Administrator access. If you don't know how to open a Command Prompt with Administrator privileges in Windows, see this helpful article.
Note: Imatest IT only supports Python versions 3.9, 3.10, 3.11 and 3.12(see IT/Python Supported Python Versions).
First, navigate to the Imatest IT Python library directory.
Windows
cd C:Program FilesImatestv26.1ITlibslibrarypython
Linux
cd /usr/local/Imatest/v26.1/IT/libs/library/python
macOS
cd /Applications/Imatest/IT/v26.1/libs/library/python
Inside this directory is the IT python package, named imatest_it-26.1.0-py2.py3-none-any.whl for Imatest IT 26.1.0.
Next, run the following command to install the Imatest IT Python module:
Windows (assuming you are running Python 3.9 installed in C:Program FilesPython39)
C:Program FilesPython39python.exe -m pip install --find-links . imatest-it
or supply the *.whl file name to pip, for example
C:Program FilesPython39python.exe -m pip install imatest_it-26.1.0-py2.py3-none-any.whl
Linux
sudo python3 -m pip install --find-links . imatest-it
or supply the *.whl file name to pip, for example
sudo python3 -m pip install imatest_it-26.1.0-py2.py3-none-any.whl
macOS
sudo -H python3 -m pip install --find-links . imatest-it
or supply the *.whl file name to pip, for example
sudo -H python3 -m pip install imatest_it-26.1.0-py2.py3-none-any.whl
You will now be able to reference Imatest IT in your Python scripts using the import statement.
使用 Imatest IT .NET 程式庫不再需要任何額外的安裝步驟。
使用 Imatest IT .NET 程式庫不再需要任何額外的安裝步驟。
為了簡化從命令列或腳本檔案呼叫 Imatest IT EXE 程式的操作,Imatest IT bin目錄應該會加入到您的PATH環境變數中。
Windows 在 Windows 系統中,此操作會在安裝過程中自動完成,但如果您在嘗試執行 EXE 程式時遇到「sfr.exe 不被識別為內部或外部命令、可運行程式或批次檔」之類的錯誤,則可能需要手動將bin目錄新增至PATH環境變數。
請依照以下說明將C:\Program Files\Imatestv26.1\ITbin加入系統PATH環境變數。您需要開啟一個新的命令視窗才能使變更生效。
為了簡化從命令列或腳本檔案呼叫 Imatest IT EXE 程式的操作,Imatest IT bin目錄應該會加入到您的PATH環境變數中。
Linux 系統上,您需要手動將 $PATH:/usr/local/Imatest/v26.1/IT/bin 加入PATH 環境變數。請參閱這些說明。
macOS 系統上,您需要手動將 $PATH:/Applications/Imatest/IT/v26.1/bin 新增至PATH 環境變數。請參閱這些說明。
第一步:準備測試環境並收集測試目標
Imatest 的分析模組需要構圖正確、光線充足的測試目標影像才能產生準確的結果。有關設定圖像測試環境的信息,請參閱這篇文章。
Imatest 提供各種測試圖表,以提高影像分析的準確性。
步驟 2:配置包含測試影像的 INI 文件
除了測試影像之外,Imatest IT 模組功能的另一個重要輸入是INI 設定文件,其中包含描述輸入影像(例如 ROI [感興趣區域])、分析詳情和輸出檔案位置的設定。在應用程式中使用 Imatest IT 之前,您需要根據具體的測試需求設定一個或多個 INI 檔案。
使用 Imatest Master 建立 INI 文件
Imatest IT 特定 INI 檔案設置
若要配置 Imatest 的 IT 特定設置,請從主視窗功能表列中選擇「設定」 ,然後選擇「IT 和通過/失敗設定...」 。有關此視窗中 IT 特定設定的詳細說明,請參閱此文章。完成更改後,按一下“確定” 。
影像分析 INI 檔案設置
當您獲得與 Imatest IT 測試所需的幀格式和尺寸相符的測試目標影像檔案後,請使用 Imatest Master 和所需的模組對其進行分析。請確保該影像的像素數與生產環境中使用的影像相同。
重複進行不同設定下的測試,直到獲得所需結果為止。
匯出 INI 文件
配置符合您需求的 IT 設定(包括感興趣區域 (ROI)、計算詳情、輸出檔案和資料夾位置)後,您可以返回 Imatest 主窗口,從選單列中選擇“INI 檔案設定”,然後選擇“儲存設定...” 。選擇 INI 檔案的儲存位置並為其指定一個有意義的名稱。當呼叫 Imatest IT 模組函數時,此檔案名稱將作為第二個輸入參數。
在Imatest中,您可以使用Imatest IT 設定視窗中的「儲存 ini 檔案」按鈕,將 ini 檔案儲存為僅包含所需部分的格式。

您可以建立一個檔案來控制最多四個模組,方法是在左側的每個框中選擇模組,然後按下「儲存 ini 檔案」 。該檔案將包含模組的 ini 部分(在上面的範例中為 [sfr] 和 [sfrreg]),以及 [imatest]、[api]、[dcraw]、[rdraw]、[sqf] 和 [visnoise](如果適用)。
步驟 3:整合並呼叫 Imatest IT 模組
現在您的測試圖像和 INI 檔案已經準備就緒,您可以整合您的應用程式並使用 Imatest IT 的模組功能來分析圖像。
請在下方選擇您偏好的介面,查看詳細說明。
Windows (Visual Studio) Project Setup
First, you need to configure your project to be able to find the Imatest IT and b Runtime libraries. To do this, right click on the project and choose Properties. Add the following include directories in the sections under Configuration Properties:
| Category | Property | Value |
|---|---|---|
| C/C++ / General | Additional Include Directories | C:Program FilesMATLABMATLAB RuntimeR2024bexterninclude C:Program FilesImatestv26.1ITlibslibraryc |
| Linker / General | Additional Include Directories | C:Program FilesMATLABMATLAB RuntimeR2024bexternlibwin64microsoft C:Program FilesImatestv26.1ITlibslibraryc |
| Linker / Input | Additional Dependencies | mclmcrrt.lib imatest_library.lib |
Note: Imatest only supports 64-bit architectures. You must use the x64 platform configuration when using Imatest IT in your projects. You may need to manually add this platform configuration to your project first. For information on how to do this, see this article.
macOS
Note: For macOS the Imatest IT C library must be used from an Objective-C wrapper. Please see the Objective-C documentation for details.
Initializing the Imatest IT Library
Now that your project references are set up, the next step is to include the imatest_library.h header file. Add this line to the top of your source file:
#include "imatest_library.h"
Next, initialize the MATLAB Runtime application state by calling mclInitializeApplication(const char **options, int count). Most users can ignore the options and count parameters; just pass in NULL and 0, respectively. The function will return 0 if successful, allowing you to trap errors and handle them gracefully. This should only be called once during the life of your application.
#include "imatest_library.h"
int main()
{
if (!mclInitializeApplication(NULL,0))
{
printf("Error: could not initialize application properly.n");
return -1001;
}
/// ...
}
The last initialization step is to call imatest_libraryInitialize(). This will prepare the Imatest IT library for use. The function also returns 0 if it is successful.
#include "imatest_library.h"
int main()
{
if (!mclInitializeApplication(NULL,0))
{
printf("Error: could not initialize the MATLAB Runtime properly.n");
return -1001;
}
if(!imatest_libraryInitialize())
{
printf("Error: could not initialize the Imatest IT library properly.n");
return -1002;
}
/// ...
}
Calling the Imatest IT C Library Interface
Now that the MATLAB Runtime and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the sfr function. The signature for the SFR module function looks like this:
bool mlfSfr_shell(int nargout, mxArray** nret, mxArray* inputFile, mxArray* rootDir, mxArray* inputKeys, mxArray* opMode, mxArray* varargin);
The Imatest IT C library encapsulates all input and output arguments inside mxArray types. This is a generic pointer type that can represent any data type. See below for more information on using mxArrays.
The Imatest IT C library parameters are listed here:
| Parameter Name | Data Type | Description |
|---|---|---|
| nargout | int | The number of expected output arguments. This will always be 1 for the JSON result string. |
| &nret | mxArray** [const char*] | The output object, which will be a string wrapped in an mxArray. |
| inputFile | mxArray* [const char*] | Image file path. A full path name may be used (and is recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the inputFile parameter is "C:ImatestiPhone6_*.jpg", all .jpg files in the folder C:Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| rootDir | mxArray* [const char*] | Directory containing your INI file. If you do not pass a file path in as the first item in the varargin parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration. |
| inputKeys | mxArray* [const char*] | This value should always be the string "JSON". XML output has been deprecated. |
| opMode | mxArray* [const char*] | String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), and how to read the values contained in the varargin parameter. If you are supplying your own full path to an INI file, and it is the first item in the varargin collection, then use one of these values: -7, -8, -10, or -17. If your INI file is named imatest-v2.ini and resides in the directory passed in as rootDir, then use one of these values: -5, -6, -9, and -15. The different opCode values direct how Imatest IT will behave. For more information on the different op modes supported by Imatest IT, see this article. |
| varargin | mxArray* [multiple const char*] | This is a catch all array structure for other parameters required by the various opModes. The contents of this array depend on which op mode you are using, and on how many images you will be processing. For information on how to populate this array, see here. |
Working with mxArrays
The Imatest IT C library receives and returns data via mxArray pointers. The MATLAB Runtime provides helper methods for allocating, interacting with, and deallocating mxArray structures.
Most of the Imatest IT C library input parameters (with the exception of varargin and raw image data passed in when using direct read mode) are strings (const char*) wrapped as mxArrays. You can create these mxArray pointers by using the mxCreateString(const char *str) function.
Before your program terminates, you must deallocate all of your mxArray pointers using the mxDestroyArray(mxArray *pm) function, and then set the pointers to NULL.
Here is an example of the typical lifecycle of an mxArray string parameter:
// Declare the pointer variable
mxArray *inputFile = NULL;
// Initialize the mxArray with a string
inputFile = mxCreateString("C:\Program Files\Imatest\v26.1\IT\samples\images\sfr_example.jpg");
// Make calls to Imatest IT library
// ...
// Destroy the mxArray
mxDestroyArray(inputFile);
inputFile = NULL;
The varargin parameter is a Matlab Cell Array containing zero or more additional input parameters, depending on the op mode. To initialize this parameter, use the mxCreateCellMatrix(int rows, int columns) function. You should create the varargin cell array with the exact number of cells required for your op mode. The rows parameter should always be 1, and the columns parameter should be the number of parameters you will be supplying.
You can then set the individual cells using mxSetCell(mxArray *array, int index, mxArray *value), where array is the varargin pointer, index is a zero-based index, and value is an mxArray pointer to the value being added to the array.
The varargin parameter is deallocated in the same way as other mxArrays, and you should not deallocate the individual cells of the array.
mxArray *varargin = NULL, *iniFile = NULL, *inputFile2 = NULL;
iniFile = mxCreateString("C:\Program Files\Imatest\v26.1\IT\samples\cpp\Imatest_INI\imatest-v2.ini");
inputFile2 = mxCreateString("C:\Program Files\Imatest\v26.1\IT\samples\images\sfr_example.jpg");
varargin = mxCreateCellMatrix(1, 2);
mxSetCell(varargin, 0, iniFile);
mxSetCell(varargin, 1, inputFile2);
// ...
mxDestroyArray(varargin);
Calling Imatest IT Modules
Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).
The first parameter will always be 1, and the second is a reference to an mxArray* pointer that will contain the JSON output of the analysis. If the function returns false, it means an error has occurred. Check the stdout and stderr streams for details on what went wrong, and see the section Error Handling below for information on handling errors gracefully.
When the call is successful, the JSON output will reside inside the outputJSON pointer. You can extract the string using the mxArrayToString(const mxArray *array_ptr) function.
if (!mlfSfr_shell(1, &outputJSON, inputFile, rootDir, inputKeys, opMode, varargin))
{
printf("*** Error calling SFR. Check output messages for details. ***n");
}
else
{
jsonOutput = mxArrayToString(outputJSON);
printf(jsonOutput);
}
When you are finished making calls to the Imatest IT C library, you then need to make three more function calls to terminate the library and the MATLAB Runtime.
mlfIt_terminate(); imatest_libraryTerminate(); mclTerminateApplication();
Windows (Visual Studio) Project Setup
First, you need to configure your project to be able to find the Imatest IT and MATLAB Runtime libraries. To do this, right click on the project and choose Properties. Add the following include directories in the sections under Configuration Properties:
| Category | Property | Value |
|---|---|---|
| C/C++ / General | Additional Include Directories | C:Program FilesMATLABMATLAB RuntimeR2024bexterninclude C:Program FilesImatestv26.1ITlibslibrarycpp |
| Linker / General | Additional Include Directories | C:Program FilesMATLABMATLAB RuntimeR2024bexternlibwin64microsoft C:Program FilesImatestv26.1ITlibslibrarycpp |
| Linker / Input | Additional Dependencies | mclmcrrt.lib imatest_library.lib |
Note: Imatest only supports 64-bit architectures. You must use the x64 platform configuration when using Imatest IT in your projects. You may need to manually add this platform configuration to your project first. For information on how to do this, see this article.
macOS
Note: For macOS the Imatest IT C++ library must be used from an Objective-C wrapper. Please see the Objective-C documentation for details.
Initializing the Imatest IT Library
Now that your project references are set up, the next step is to include the imatest_library.h header file. Add this line to the top of your source file:
#include "imatest_library.h"
Next, initialize the MATLAB Runtime application state by calling mclInitializeApplication(const char **options, int count). Most users can ignore the options and count parameters; just pass in NULL and 0, respectively. The function will return 0 if successful, allowing you to trap errors and handle them gracefully.
#include "imatest_library.h"
int main()
{
if (!mclInitializeApplication(NULL,0))
{
std::cerr << "Error: could not initialize the MATLAB Runtime properly." << std::endl;
return -1001;
}
/// ...
}
The last initialization step is to call imatest_libraryInitialize(). This will prepare the Imatest IT library for use. The function also returns 0 if it is successful.
#include "imatest_library.h'
int main()
{
if (!mclInitializeApplication(NULL,0))
{
std::cerr << "Error: could not initialize the MATLAB Runtime properly." << std::endl;
return -1001;
}
if(!imatest_libraryInitialize())
{
std::cerr << "Error: could not initialize the Imatest IT library properly." << std::endl;
return -1002;
}
/// ...
}
Calling the Imatest IT C++ Library Interface
Now that the MATLAB Runtime and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the sfr function. The signature for the SFR module function looks like this:
void sfr_shell(int nargout, mwArray& nret, const mwArray& inputFile, const mwArray& rootDir, const mwArray& inputKeys, const mwArray& opMode, const mwArray& varargin);
The Imatest IT C++ library encapsulates all input and output arguments inside mwArray objects. This is a generic wrapper class that can represent any data type. See below for more information on using mwArrays.
The Imatest IT C++ library parameters are listed here:
| Parameter Name | Data Type | Description |
|---|---|---|
| nargout | int | The number of expected output arguments. This will always be 1 for the JSON result string. |
| nret | mwArray& [const char*] | The output object, which will be a string wrapped in an mwArray object. |
| inputFile | mwArray& [const char*] | Image file path. A full path name may be used (and is recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the inputFile parameter is "C:ImatestiPhone6_*.jpg", all .jpg files in the folder C:Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| rootDir | mwArray& [const char*] | Directory containing your INI file. If you do not pass a file path in as the first item in the varargin parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration. |
| inputKeys | mwArray& [const char*] | This value should always be the string "JSON". XML output has been deprecated. |
| opMode | mwArray& [const char*] | String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), and how to read the values contained in the varargin parameter. If you are supplying your own full path to an INI file, and it is the first item in the varargin collection, then use one of these values: -7, -8, -10, or -17. If your INI file is named imatest-v2.ini and resides in the directory passed in as rootDir, then use one of these values: -5, -6, -9, and -15. The different opCode values direct how Imatest IT will behave. For more information on the different op modes supported by Imatest IT, see this article. |
| varargin | mwArray& [multiple const char*] | This is a catch all array structure for other parameters required by the various op modes. The contents of this array depend on which op mode you are using, and on how many images you will be processing. For information on how to populate this array, see here. |
Working with mwArrays
The Imatest IT C++ library receives and returns data via mwArray objects. Unlike the C library, the C++ library's mwArray class is object-oriented, and also takes care of allocating and deallocating automatically. There is no need to manually destroy the mwArray objects.
Most of the Imatest IT C++ library input parameters (with the exception of varargin and raw image data passed in when using direct read mode) are strings (const char) wrapped as mwArray objects. You can create these mwArray pointers by passing a const char into the constructor.
mwArray opMode("-5");
The varargin parameter is a Matlab Cell Array containing zero or more additional input parameters, depending on the opMode. To initialize this parameter, use the mwArray(int num_rows, int num_cols, mxClassID mxID) constructor, passing 1 for num_rows, the number of extra arguments required as num_cols, and the constant mxCELL_CLASS as mxID. The num_cols value should be the exact number of cells required for your op mode. See this article for more information on populating the varargin parameter.
You can then set the individual cells using the mwArray object's Get(int row, int column) and Set(const mwArray& arr) methods. Note that the row and column parameters are 1-based indexes.
/// Set the first cell of varargin to be the iniFilePath varargin.Get(1,1).Set(iniFilePath);
Calling Imatest IT Modules
Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).
The first parameter will always be 1, and the second is a reference to an uninitialized mwArray variable that will contain the JSON output of the analysis. If the function throw an exception, it means an error has occurred. Check the exception messages and stdout and stderr streams for details on what went wrong. See the section on Error Handling below for more information on catching and handling exceptions gracefully.
When the call is successful, the JSON output will reside inside the outputJSON pointer. You can extract the string by calling the mwArray.ToString() method, then converting that result to a const char*. Note that you must declare the mwString variable separately for this to work.
sfr_shell(1, outputJSON, inputFile, rootDir, inputKeys, opMode, varargin)
mwString mwStr = outputJSON.ToString();
const char* strOutputJSON = (const char*)mwStr;
std::cout << strOutputJSON << std::endl;
When you are finished making calls to the Imatest IT C++ library, you then need to make three more function calls to terminate the library and the Matlab Runtime.
it_terminate(); imatest_libraryTerminate(); mclTerminateApplication();
XCode Project Setup
First, you need to configure your project to be able to find the Imatest IT and MATLAB Runtime libraries. To do this, in the project editor, go to Build Settings and add the follow paths and linker flags:
| Category | Property | Value |
|---|---|---|
| Search Paths | Header Search Paths | /Applications/Imatest/IT/v26.1/libs/library/cpp /Applications/MATLAB/MATLAB_Runtime/R2024b/extern/include |
| Search Paths | Library Search Paths | /Applications/Imatest/IT/v26.1/libs/library/cpp /Applications/MATLAB/MATLAB_Runtime/R2024b/runtime/maci64 |
| Linking | Other Linker Flags | -lmwmclmcrrt -lImatest |
Note: Imatest only supports the x86_64 architecture.
Next, in the General pane,
-
- Go to the Linked Frameworks and Libraries section
-
- Click the + button
-
- Click the Add Other... button
-
- Navigate to /Applications/Imatest/IT/v26.1/libs/library/cpp
-
- select libImatest.dylib and click Open.
-
- Add Cocoa.Framework in a similar fashion if it has not been added.
Additional step for Apple Silicon
In order to avoid an error in MATLAB Runtime execution, for Apple Silicon builds only please define the following environment variable prior to execution:
MW_OUT_PROCESS=1
Adding Symbolic Breakpoints to XCode projects
When the MATLAB Runtime initializes it emits SIGSEGV and SIGBUS. The MATLAB Runtime will properly handle this issue on its own if left to do so. The easiest way deal with this in XCode is to set symbolic break points and add commands that instruct the debugger to ignore these signals. Without these commands, the debugger will break on those signals when the MATLAB Runtime initializes and runs.
-
- Go to Debug:Break Points:Create Symbolic Breakpoint.
-
- In the Symbol field, type NSApplicationMain
-
- Set the Action dropdown to 'Debugger Command'
-
- In the command field enter process handle --pass true --stop false --notify true SIGSEGV
-
- Check 'Automatically continue after evaluating'
-
- Repeat steps 1-5 adding another symbolic with the following command process handle --pass true --stop false --notify true SIGBUS
Initializing the Imatest IT Library
Now that your project references are set up, the next step is to include the libImatest.h header file. Add these lines after your other includes and imports:
#define HRESULT HRESULT_MATLAB
#include "libImatest.h"
#include "mclmcrrt.h"
#include "mclcppclass.h"
#undef HRESULT
Note that mclmcrrt.h defines HRESULT, which is also defined by Cocoa headers, so we use the preprocessor to redefine HRESULT in mclmcrrt.h and dependent header files to resolve the conflict.
Next, initialize the MATLAB Runtime application state by calling mclInitializeApplication(const char **options, int count). Most users can ignore the options and count parameters; just pass in NULL and 0, respectively. The function will return 0 if successful, allowing you to trap errors and handle them gracefully. This should only be called once during the life of your application. The last initialization step is to call libImatestInitialize(). This will prepare the Imatest IT library for use. The function also returns 0 if it is successful. Since in Cocoa all non-GUI methods cannot run on the main thread, detach a thread to run the method. The methods below are added to the AppDelegate class for the UI.
- (void) applicationWillFinishLaunching:(NSNotification *)aNotification
{
NSLog(@"Processing applicationWillFinishLaunching event");
[NSThread detachNewThreadSelector:@selector(initApp:) toTarget:self withObject:nil];
}
- (void)initApp:(id)param
{
@autoreleasepool {
NSLog(@"Executing initialization thread...");
mclmcrInitialize();
if (!mclInitializeApplication(NULL,0))
{
NSString *stringError =
[NSString stringWithCString:mclGetLastErrorMessage()
encoding:NSMacOSRomanStringEncoding];
NSLog(@"Initializing the MATLAB Runtime failed");
NSLog(@"%@", stringError);
return;
}
NSLog(@"Initializing Imatest IT library");
if (!libImatestInitialize()
{
NSString *stringError =
[NSString stringWithCString:mclGetLastErrorMessage()
encoding:NSMacOSRomanStringEncoding];
NSLog(@"Initializing the IT library failed");
libImatestPrintStackTrace();
NSLog(@"%@", stringError);
return;
}
NSLog(@"Initialized");
}
}
Calling the Imatest IT C++ Library Interface
Now that the MATLAB Runtime and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the sfrplus function. The signature for the SFR module function looks like this:
void sfrplus_shell(int nargout, mwArray& nret, const mwArray& inputFile, const mwArray& rootDir, const mwArray& inputKeys, const mwArray& opMode, const mwArray& varargin);
The Imatest IT C++ library encapsulates all input and output arguments inside mwArray objects. This is a generic wrapper class that can represent any data type. See below for more information on using mwArrays.
The Imatest IT C++ library parameters are listed here:
| Parameter Name | Data Type | Description |
|---|---|---|
| nargout | int | The number of expected output arguments. This will always be 1 for the JSON result string. |
| nret | mwArray& [const char*] | The output object, which will be a string wrapped in an mwArray object. |
| inputFile | mwArray& [const char*] | Image file path. A full path name may be used (and is recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the inputFile parameter is "C:ImatestiPhone6_*.jpg", all .jpg files in the folder C:Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| rootDir | mwArray& [const char*] | Directory containing your INI file. If you do not pass a file path in as the first item in the varargin parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration. |
| inputKeys | mwArray& [const char*] | This value should always be the string "JSON". XML output has been deprecated. |
| opMode | mwArray& [const char*] | String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), and how to read the values contained in the varargin parameter. If you are supplying your own full path to an INI file, and it is the first item in the varargin collection, then use one of these values: -7, -8, -10, or -17. If your INI file is named imatest-v2.ini and resides in the directory passed in as rootDir, then use one of these values: -5, -6, -9, and -15. The different opCode values direct how Imatest IT will behave. For more information on the different op modes supported by Imatest IT, see this article. |
| varargin | mwArray& [multiple const char*] | This is a catch all array structure for other parameters required by the various op modes. The contents of this array depend on which op mode you are using, and on how many images you will be processing. For information on how to populate this array, see here. |
Working with mwArrays
The Imatest IT C++ library receives and returns data via mwArray objects. Unlike the C library, the C++ library's mwArray class is object-oriented, and also takes care of allocating and deallocating automatically. There is no need to manually destroy the mwArray objects.
Most of the Imatest IT C++ library input parameters (with the exception of varargin and raw image data passed in when using direct read mode) are strings (const char) wrapped as mwArray objects. You can create these mwArray pointers by passing a const char into the constructor.
mwArray opMode("-5");
The varargin parameter is a Matlab Cell Array containing zero or more additional input parameters, depending on the opMode. To initialize this parameter, use the mwArray(int num_rows, int num_cols, mxClassID mxID) constructor, passing 1 for num_rows, the number of extra arguments required as num_cols, and the constant mxCELL_CLASS as mxID. The num_cols value should be the exact number of cells required for your op mode. See this article for more information on populating the varargin parameter.
You can then set the individual cells using the mwArray object's Get(int row, int column) and Set(const mwArray& arr) methods. Note that the row and column parameters are 1-based indexes.
/// Set the first cell of varargin to be the iniFilePath varargin.Get(1,1).Set(iniFilePath);
Calling Imatest IT Modules
Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).
The first parameter will always be 1, and the second is a reference to an uninitialized mwArray variable that will contain the JSON output of the analysis. If the function throw an exception, it means an error has occurred. Check the exception messages and stdout and stderr streams for details on what went wrong. See the section on Error Handling below for more information on catching and handling exceptions gracefully.
When the call is successful, the JSON output will reside inside the outputJSON mwArray.
- (void)postTest: (id)param
{
@autoreleasepool {
try{
// Declare and initialize outputJSON, fileParam, pathParam, keysParam, modeParam, and varargin mwArray's
NSLog(@"Running test.");
sfrplus_shell(1, outputJSON, fileParam, pathParam, keysParam, modeParam, varargin);
// Process JSON returned in outputJSON mwArray
} catch (mwException ex){
NSLog(@"Error");
NSLog(@"%s", ex.what());
ex.print_stack_trace();
}
}
}
- (void)runTest
{
// Start a new thread to run sfrplus_shell()
[NSThread detachNewThreadSelector:@selector(postTest:) toTarget:self withObject:nil];
}
The JSON string returned in outputJSON has UTF-16 encoding. This can be converted to a NSString with the following
auto numel = outputJSON.NumberOfElements();
std::u16string buffer(numel+1, 0);
outputJSON.GetCharData(&abuffer[0], numel);
char* data = (char*)buffer.data();
unsigned long size = buffer.size()*sizeof(char16_t);
NSString* jsonString =[[NSString alloc] initWithBytes:data length:size encoding:NSUTF16LittleEndianStringEncoding];
When you are finished making calls to the Imatest IT C++ library, you then need to make three more function calls (it_terminate(), libImatestTerminate(), and mclTerminateApplication) to terminate the library and the Matlab Runtime.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
[NSThread detachNewThreadSelector:@selector(terminateApp:) toTarget:self withObject:sender];
return NSTerminateLater;
}
-(void)terminateApp:(NSApplication *)theApplication
{
NSLog(@"Executing termination thread");
it_terminate();
libImatestTerminate();
mclTerminateApplication();
[theApplication replyToApplicationShouldTerminate: YES];
}
Note: Imatest only supports 64-bit architectures. You must use the 64-bit version of Python when using Imatest IT.
Calling the Imatest IT Python Interface
At the top of your script file, include this line to import the ImatestLibrary class from the imatest.it module:
from imatest.it import ImatestLibrary
Next, create an instance of the ImatestLibrary class. Behind the scenes, the ImatestLibrary constructor will start up the Matlab MCR Runtime and load all the IT libraries into memory. This will take a few seconds the first time you run it, but should be faster on subsequent runs, especially if you have set your system's environment variables to the recommended values as described above.
from imatest.it import ImatestLibrary
imatestLib = ImatestLibrary()
Now that the Matlab MCR and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the sfr function. The signature for the SFR module function looks like this:
sfr(input_file=None, root_dir=None, op_mode=None, ini_file=None, raw_data=None, json_args=None)
The Imatest IT Python library parameters are listed here:
| Parameter Name | Data Type | Description |
|---|---|---|
| input_file | string or list | Image file path. A full path name may be used (and is recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If a relative path name is used, the path is relative to your calling program, not the value of the root_dir parameter. Multiple files can be analyzed by passing in a list of file names, or by using a wildcard (*) symbol in the path. For example, if the input_file parameter is "C:ImatestiPhone6_*.jpg", all .jpg files in the folder C:Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| root_dir | string | Directory containing your INI file. If you do not pass a file path in as the ini_file parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration. |
| op_mode | string | String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), or if you are using Direct Read mode. Valid values for the op_mode parameter are found in constants of the ImatestLibrary class: ImatestLibrary.OP_MODE_SEPARATE, ImatestLibrary.OP_MODE_SIGNAL_AVERAGE, ImatestLibrary.OP_MODE_TEMPORAL, and ImatestLibrary.OP_MODE_DIRECT_READ. For more information on the different op modes supported by Imatest IT, see this article. |
| ini_file | string (optional) | If you want to use an INI file that is not named imatest-v2.ini, you will need to supply the path to the file as the ini_file parameter. |
| raw_data | string (optional) | The raw image data. Only used when using OP_MODE_DIRECT_READ. For more information on direct read mode, see this article. |
| json_args | string (optional) | A JSON string containing metadata about how to interpret the image in the raw_data parameter. Only used when using OP_MODE_DIRECT_READ. For more information on direct read mode, see this article. |
Calling Imatest IT Modules
Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).
It's easiest to call the sfr using named parameters, as shown below. An exception will be thrown if something goes wrong - you should catch it and handle it gracefully. Check the exception message and stdout and stderr streams for details on what went wrong, and see the Error Handling section below for more information on gracefully handling exceptions.
When the call is successful, the function will return a string containing JSON-encoded output.
from imatest.it import ImatestLibrary
import json
imatestLib = ImatestLibrary()
result = imatestLib.sfr(input_file=input_file,
root_dir=root_dir,
op_mode=ImatestLibrary.OP_MODE_SEPARATE,
ini_file=ini_file)
print(result)
When you are finished making calls to the Imatest IT Python library, you then need to call terminate_library() to unload the library and the Matlab Runtime.
imatestLib.terminate_library();
Running the Imatest IT Python library on macOS
Note: Due to a limitation in how the IT Python library is constructed, you must call any python code via the mwpython.sh script provided by Mathworks at /Applications/MATLAB/MATLAB_Runtime/R2024b/bin. It is recommended that you set the PYTHON_HOME environment variable if you wish to use a particular python interpreter. Also, the only supported means to call mwpython is to call a script directly (not a module using the -m flag in python). For example
export PATH=/Applications/MATLAB/MATLAB_Runtime/R2024b/bin:$PATH
export PYTHON_HOME=/Library/Frameworks/Python.framework/Versions/3.9
mwpython some_script.py
Windows (Visual Studio) Project Setup
To use the Imatest IT .NET libraries in your Visual Studio project, first you need to add a reference to the library DLL in your project.
Once your project is created in Visual Studio, right click on the References section of the Solution Explorer and choose Add Reference….

In the Reference Manager window, choose Browse on the left-hand side, then click the Browse… button at the bottom.

Navigate to the .NET library directory of your Imatest IT installation (by default, C:Program FilesImatestv26.1ITlibslibrary.NET.NET 4.8 for .NET Framework 4.8 and C:Program FilesImatestv26.1ITlibslibrary.NET.NET 9.0 for .NET 9.0 ), choose Imatest.IT.dll, and click the Add button.
Note: You do not need to add the IT.dll reference to your project.

Click OK to close the Reference Manager window.
Note: Imatest only supports 64-bit architectures. You must use the x64 platform when running .NET applications. The Any CPU platform will throw runtime errors.
Calling the Imatest IT .NET Interface
using Imatest.IT;
Next, create an instance of the Imatest.IT.Library class. Behind the scenes, the Imatest.IT.Library constructor will start up the Matlab MCR Runtime and load all the IT libraries into memory. This will take a few seconds the first time you run it, but should be faster on subsequent runs, especially if you have set your system's environment variables to the recommended values as described above.
Imatest.IT.Library implements the IDisposable interface, and we recommend that you wrap your library instance inside of a using statement to ensure that the Dispose() method is called properly. The Dispose() method cleans up the Matlab Runtime, and also releases your floating license seat, if you are using a floating license.
using Imatest.IT;
class Program
{
static void Main(string[] args)
{
using (Library itLib = new Library())
{
// ....
}
}
}
Now that the Matlab MCR and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same overloaded method signatures (with the exception of OIS). In this example, we will use the SFR.JSON methods. The signatures for the SFR module function looks like this:
string SFR.JSON(string rootDir, string inputFile, OperationMode opMode) string SFR.JSON(string rootDir, IEnumerable<string> inputFiles, OperationMode opMode) string SFR.JSON(string rootDir, string inputFile, OperationMode opMode, string iniFilePath) string SFR.JSON(string rootDir, IEnumerable<string> inputFiles, OperationMode opMode, string iniFilePath) string SFR.JSON(string rootDir, byte[] inputBytes, DirectReadOptions directReadOptions) string SFR.JSON(string rootDir, byte[] inputBytes, DirectReadOptions directReadOptions, string iniFilePath)
The Imatest IT .NET library parameters are listed here:
| Parameter Name | Data Type | Description |
|---|---|---|
| rootDir | string | Directory containing your default INI file. If you do not pass a file path in as optional the iniFile parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration. |
| inputFile | string | Image file path. A full path name may be used (and is recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is "C:ImatestiPhone6_*.jpg", all .jpg files in the folder C:Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| inputFiles | IEnumerable<string> | A list of image file paths. Full path names may be used (and are recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If relative path names are used, the path is relative to your calling program, not the value of the rootDir parameter. |
| opMode | OperationMode | Enum value for one of the available operation modes, which tells Imatest IT how to analyze your image(s). Valid values for the opMode parameter are: OperationMode.Separate, OperationMode.SignalAverage, and OperationMode.Temporal. For more information on the different op modes supported by Imatest IT, see this article. |
| iniFile | string (optional) | If you want to use an INI file that is not named imatest-v2.ini, you will need to supply the path to the file as the iniFile parameter. |
| inputBytes | byte[], ushort[], or uint[] (optional) | The raw image data. Only used if you are passing in image data directly using Direct Read Mode. For more information on direct read mode, see this article. |
| directReadOptions | DirectReadOptions (optional) | A an object containing metadata about how to interpret the image in the inputBytes parameter. Only used when using Direct Read Mode. For more information on direct read mode, see this article. |
Calling Imatest IT Modules
Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).
We recommend always wrapping your Imatest IT calls in try/catch blocks. If anything goes wrong, an Exception will be thrown. You should handle these exceptions gracefully. Check the exception message for details on what went wrong, and see the section on Error Handling below for more information.
When the call is successful, the function will return a string containing JSON-encoded output.
using Imatest.IT;
class Program
{
static void Main(string[] args)
{
using (Library itLib = new Library())
{
try {
string result = itLib.SFR.JSON(rootDir, inputFile, OperationMode.Separate, iniFilePath);
} catch (Exception ex) {
Console.Out.WriteLine(ex.Message);
}
}
}
}
Windows (Visual Studio) Project Setup
To use the Imatest IT .NET libraries in your Visual Studio project, first you need to add a reference to the library DLL in your project.
Once your project is created in Visual Studio, right click on the References section of the Solution Explorer and choose Add Reference….

In the Reference Manager window, choose Browse on the left-hand side, then click the Browse… button at the bottom.

Navigate to the .NET library directory of your Imatest IT installation (by default, C:Program FilesImatestv26.1ITlibslibrary.NET.NET 4.8 for .NET Framework 4.8 and C:Program FilesImatestv26.1ITlibslibrary.NET.NET 9.0 for .NET 9.0), choose Imatest.IT.dll, and click the Add button.
Note: You do not need to add the IT.dll reference to your project.

Click OK to close the Reference Manager window.
Note: Imatest only supports 64-bit architectures. You must use the x64 platform when running .NET applications. The Any CPU platform will throw runtime errors.
Calling the Imatest IT .NET Interface
At the top of your source code file, add an Imports statement for Imatest.IT:
Imports Imatest.IT
Next, create an instance of the Imatest.IT.Library class. Behind the scenes, the Imatest.IT.Library constructor will start up the Matlab MCR Runtime and load all the IT libraries into memory. This will take a few seconds the first time you run it, but should be faster on subsequent runs, especially if you have set your system's environment variables to the recommended values as described above.
Imatest.IT.Library implements the IDisposable interface, and we recommend that you wrap your library instance inside of a Using statement to ensure that the Dispose() method is called properly. The Dispose() method cleans up the Matlab Runtime, and also releases your floating license seat, if you are using a floating license.
Imports Imatest.IT
Module Program
Sub Main()
Using itLib = New Library()
' ...
End Using
End Sub
End Module
Now that the Matlab MCR and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same overloaded method signatures (with the exception of OIS). In this example, we will use the SFR.JSON methods. The signatures for the SFR module function looks like this:
SFR.JSON(String rootDir, String inputFile, OperationMode opMode) As String SFR.JSON(String rootDir, IEnumerable(Of String) inputFiles, OperationMode opMode) As String SFR.JSON(String rootDir, String inputFile, OperationMode opMode, String iniFilePath) As String SFR.JSON(String rootDir, IEnumerable(Of String) inputFiles, OperationMode opMode, String iniFilePath) As String SFR.JSON(String rootDir, Byte() inputBytes, DirectReadOptions directReadOptions) As String SFR.JSON(String rootDir, Byte() inputBytes, DirectReadOptions directReadOptions, String iniFilePath) As String
The Imatest IT .NET library parameters are listed here:
| Parameter Name | Data Type | Description |
|---|---|---|
| rootDir | String | Directory containing your default INI file. If you do not pass a file path in as optional the iniFile parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration. |
| inputFile | String | Image file path. A full path name may be used (and is recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is "C:ImatestiPhone6_*.jpg", all .jpg files in the folder C:Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| inputFiles | IEnumerable(Of String) | A list of image file paths. Full path names may be used (and are recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If relative path names are used, the path is relative to your calling program, not the value of the rootDir parameter. |
| opMode | OperationMode | Enum value for one of the following operation codes, which tells Imatest IT how to analyze your image(s). Valid values for the opMode parameter are: OperationMode.Separate, OperationMode.SignalAverage, and OperationMode.Temporal. For more information on the different op modes supported by Imatest IT, see this article. |
| iniFile | String (optional) | If you want to use an INI file that is not named imatest-v2.ini, you will need to supply the path to the file as the iniFile parameter. |
| inputBytes | Byte(), UShort(), or UInteger() (optional) | The raw image data. Only used if you are passing in image data directly using Direct Read Mode. For more information on direct read mode, see this article. |
| directReadOptions | DirectReadOptions (optional) | A an object containing metadata about how to interpret the image in the inputBytes parameter. Only used when using Direct Read Mode. For more information on direct read mode, see this article. |
Calling Imatest IT Modules
Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).
We recommend always wrapping your Imatest IT calls in try/catch blocks. If anything goes wrong, an Exception will be thrown. You should handle these exceptions gracefully. Check the exception message for details on what went wrong, and see the section on Error Handling below for more information.
When the call is successful, the function will return a string containing JSON-encoded output.
Imports Imatest.IT
Module Program
Sub Main()
Using itLib = New Library()
Try
Dim result = itLib.SFR.JSON(rootDir, imagePath, OperationMode.Separate, iniFilePath)
Catch ex As Exception
Console.Out.WriteLine(ex.Message)
End Try
End Using
End Sub
End Module
Calling the Imatest IT EXE Interface
The Imatest IT EXE Library can be called using Windows or Linux script files. We recommend making sure that the IT bin directory is in your PATH variable. On Windows, this should already happen when Imatest IT is installed. You may need to add to your path manually on Linux. For more information on viewing and editing system environment variables, see this article.
All Imatest IT EXE executables accept the following arguments (except for OIS, which uses different inputs):
sfr.exe op-mode input-file bin-directory ini-file [result-directory] [other-images ...]
The Imatest IT EXE library parameters are listed here:
| Parameter Name | Description |
|---|---|
| op_mode | One of the following operation codes, which tells Imatest IT how to analyze your image(s). Valid values for the op_mode parameter are: -1 (Separate Analysis), -11 (Signal Average Analysis), and -12 (Temporal Noise Analysis). For more information on the different op modes supported by Imatest IT, see this article. |
| input-file | Image file path. A full path name may be used (and is recommended), such as "C:Program FilesImatestv26.1ITsamplesimagessfr_example.jpg". If a relative path name is used, the path is relative to your calling program. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is "C:ImatestiPhone6_*.jpg", all .jpg files in the folder C:Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| bin-directory | The location of the Imatest IT bin directory. By default, this will be "C:Program FilesImatestv26.1ITbin". |
| ini-file | The full path to the INI configuration file you will be using. |
| result-directory | The directory where Imatest IT's output files will be written to. |
| other-images | The path(s) to other images that will be analyzed besides the initial input-file image. |
Calling Imatest IT Modules
Imatest IT EXE modules are called using the command line, or in .bat files.
Note: You should not include a trailing '' when passing in directory names, otherwise you may get an error (see here).
sfr.exe "-1" "C:ImatestSamplessfr_example.jpg" "C:Program FilesImatestv26.1ITbin" "C:ImatestSamplesimatest-v2.ini" "C:ImatestSamplesResults"
When the module is finished running, the result files will be written to the result-directory folder (in this case, C:ImatestSamplesResults).
Calling the Imatest IT EXE Interface
The Imatest IT EXE Library can be called using macOS or Linux Bash script files. We recommend making sure that the IT bin directory is in your PATH variable. You may need to add to your path manually on macOS and Linux. For more information on viewing and editing system environment variables, see this article.
All Imatest IT EXE executables accept the following arguments (except for OIS, which uses different inputs):
./run_sfr.sh op-mode input-file bin-directory ini-file [result-directory] [other-images ...]
The Imatest IT EXE library parameters are listed here:
| Parameter Name | Description |
|---|---|
| op_mode | One of the following operation codes, which tells Imatest IT how to analyze your image(s). Valid values for the op_mode parameter are: -1 (Separate Analysis), -11 (Signal Average Analysis), and -12 (Temporal Noise Analysis). For more information on the different op modes supported by Imatest IT, see this article. |
| input-file | Image file path. A full path name may be used (and is recommended), such as "/Applications/Imatest/IT/v26.1/samples/images/sfr_example.jpg". If a relative path name is used, the path is relative to your calling program. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is "$HOME/Imatest/iPhone6_*.jpg", all .jpg files in the folder $HOME/Imatest with filenames beginning with "iPhone6_" will be analyzed. |
| bin-directory | The location of the Imatest IT bin directory. By default, this will be "/Applications/Imatest/IT/v26.1/bin" on macOS, and "/usr/local/Imatest/v26.1/IT/bin" on Linux. |
| ini-file | The full path to the INI configuration file you will be using. |
| result-directory | The directory where Imatest IT's output files will be written to. |
| other-images | The path(s) to other images that will be analyzed besides the initial input-file image. |
Calling Imatest IT Modules
Imatest IT EXE modules are called using the command line with the .sh files.
Note: You should not include a trailing '' when passing in directory names, otherwise you may get an error (see here).
./run_sfr.sh "-1" "$HOME/ImatestSamples/sfr_example.jpg" "/Applications/Imatest/IT/v26.1/bin" "$HOME/ImatestSamples/imatest-v2.ini" "$HOME/ImatestSamples/Results"
When the module is finished running, the result files will be written to the result-directory folder (in this case, $HOME/ImatestSamples/Results).
Step 4: Process the Results
The Imatest IT module functions output their results as JSON, XML, and CSV formatted text files. The C, C++, Python, and .NET libraries also return results as a JSON formatted string to the calling program.
Using the JSON Result in Code
Imatest IT's JSON result string, which is returned to the calling program, can be parsed and processed using third party JSON libraries. A list of JSON libraries for several languages can be found at json.org.
The result strings are packaged as nested property/value objects, and the first property is always [module]Results, as seen in this excerpt from an SFRplus call:
Note: If you analyze multiple files in a single call, only the last file's results will be returned to the calling program. The others will be written to output files in the Results directory.
If you find that a result you need is missing from the returned JSON, please contact us and we can add it in the next minor release of Imatest IT.
Imatest IT Output Files
Imatest IT also writes its results to text files, which are formatted in XML, CSV, and JSON. By default, these files are written to a Results folder in the same folder as the images themselves. You can change the location by using Imatest Master to change your INI configuration settings, in the Auto mode settings for the modules you will be using:

Performance Tip: If you do not need some or all of the output files, you can disable them using the same Auto mode settings window. This will make your Imatest IT calls run a little faster. Just uncheck each of the outputs that you do not require.
Error Handling
Select your preferred interface below to see the best ways to handle errors using Imatest IT.
In the Imatest C library, if an error occurs within one of the analysis module functions, a false result will be returned. You can then use the mlfGetExceptionID(int nargout, mxArray** errID, mxArray** errName) function to extract an Error ID and Error Name, which map into the Imatest IT Exception Hierarchy.
To make handling these exceptions easier, Imatest IT includes an optional header file, imatest_exception_IDs.h, which maps each of the Error IDs to an enum. To include this header file, add #include "imatest_exception_ids.h" to your source file. You can read more about the Exception Hierarchy here.
Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT C Library:
int retVal;
mxArray *errorID = NULL, *errorName = NULL;
enum ImatestExceptionIDs errorCode;
const char* errorNameStr;
...
if (!mlfSfr_shell(nargout, &outputJSON, inputFile, rootDir, inputKeys, opMode, varargin))
{
if (mlfGetExceptionID(2, &errorID, &errorName))
{
errorCode = (enum ImatestExceptionIDs)mxGetScalar(errorID);
printf("*** Error ID: %dn", errorCode);
switch (errorCode)
{
case kImatestFileNotFoundException:
printf("File not found exception.n");
break;
case kBadFramingException:
printf("Bad framing exception.n");
break;
default:
errorNameStr = mxArrayToString(mxGetCell(errorName, 0));
printf("*** Unexpected Error: %sn", errorNameStr);
break;
}
mxDestroyArray(errorID);
mxDestroyArray(errorName);
retVal = errorCode;
}
else {
printf("*** Unknown Error.n");
retVal = -1005;
}
}
else
{
retVal = 0;
...
}
In the Imatest C++ library, if an error occurs within one of the analysis module functions, an mwException will be thrown. If you catch the exception, then you can use the getExceptionID(int nargout, mwArray& errID, mwArray& errName) function to extract an Error ID and Error Name, which map into the Imatest IT Exception Hierarchy.
To make handling these exceptions easier, Imatest IT includes an optional header file, imatest_exception_IDs.h, which maps each of the Error IDs to an enum. To include this header file, add #include "imatest_exception_ids.h" to your source file. You can read more about the Exception Hierarchy here.
Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT C++ Library:
try
{
sfr_shell(1, outputJSON, inputFile, rootDir, inputKeys, opMode, varargin)
}
catch (const mwException& e)
{
mwArray mwErrorID, mwErrorName;
mwString mwErrorNameStr;
getExceptionID(2, mwErrorID, mwErrorName);
int err = (int)mwErrorID;
switch (err)
{
case imatest::kImatestFileNotFoundException:
std::cerr << "*** File was not found. Check the file path." << std::endl;
break;
case imatest::kBadFramingException:
std::cerr << "*** Image is not framed correctly." << std::endl;
break;
default:
mwErrorNameStr = mwErrorName.Get(1,1).ToString();
std::cerr << "*** Unexpected Error: " << mwErrorNameStr << std::endl;
break;
}
retVal = err;
}
In the Imatest C++ library, if an error occurs within one of the analysis module functions, an mwException will be thrown. If you catch the exception, then you can use the getExceptionID(int nargout, mwArray& errID, mwArray& errName) function to extract an Error ID and Error Name, which map into the Imatest IT Exception Hierarchy.
To make handling these exceptions easier, Imatest IT includes an optional header file, imatest_exception_IDs.h, which maps each of the Error IDs to an enum. To include this header file, add #include "imatest_exception_ids.h" to your source file. You can read more about the Exception Hierarchy here.
Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT C++ Library with Objective-C++:
- (void)postTest: (id)param
{
@autoreleasepool {
try{
// Declare and initialize outputJSON, fileParam, pathParam, keysParam, modeParam, and varargin mwArray's
NSLog(@"Running test.");
sfrplus_shell(1, outputJSON, fileParam, pathParam, keysParam, modeParam, varargin);
// Process JSON returned in outputJSON mwArray
} catch (mwException ex) {
mwArray mwErrorID, mwErrorName;
mwString mwErrorNameStr;
getExceptionID(2, mwErrorID, mwErrorName);
int err = (int)mwErrorID;
switch (err)
{
case imatest::kImatestFileNotFoundException:
NSLog(@"*** File was not found. Check the file path.");
break;
case imatest::kBadFramingException:
NSLog(@"*** Image is not framed correctly.");
break;
default:
mwErrorNameStr = mwErrorName.Get(1,1).ToString();
NSLog(@"*** Unexpected Error: %s", (const char*)mwErrorNameStr);
break;
}
retVal = err;
}
}
}
- (void)runTest
{
// Start a new thread to run sfrplus_shell()
[NSThread detachNewThreadSelector:@selector(postTest:) toTarget:self withObject:nil];
}
In the Imatest Python library, if an error occurs within one of the analysis module functions, an ImatestException will be thrown. If you catch the exception, then you can get more information about using the error_id, error_name, and message properties.
Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT Python Library. You can use the constants on the ImatestException class to handle certain error types in different ways. In this example, an ImatestException will be thrown because all floating license seats are currently being used:
from imatest.it import ImatestLibrary, ImatestException
...
try:
result = imatestLib.sfr(input_file=input_file,
root_dir=root_dir,
op_mode=ImatestLibrary.OP_MODE_SEPARATE,
ini_file=ini_file)
except ImatestException as ex:
if iex.error_id == ImatestException.FloatingLicenseException:
print("All floating license seats are in use. Exit Imatest on another computer and try again.")
elif iex.error_id == ImatestException.LicenseException:
print("License Exception: " + iex.message)
else:
print("*** Error calling sfr: %s" % (iex.message, ))
In the Imatest .NET library, if an error occurs within one of the analysis module functions, an Exception will be thrown. If you catch the exception, then you can get more information about it by calling the ImatestLibrary.GetLastException() and ImatestLibrary.GetExceptionName() methods.
Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT .NET Library:
try
{
string result = itLib.SFRplus.JSON(rootDir, imagePath, OperationMode.Separate, iniFile);
}
catch (Exception ex)
{
ImatestException iex = lib.GetLastException();
string errorName = lib.GetExceptionName();
if (iex == ImatestException.FloatingLicenseException)
{
Console.Out.WriteLine("All floating license seats are in use. Exit Imatest on another computer and try again.");
}
else if (iex == ImatestException.LicenseException)
{
Console.Out.WriteLine("License Exception: {0}: {1}", errorName, ex.Message);
}
else
{
Console.Out.WriteLine("An error has occurred:");
Console.Out.WriteLine(ex.Message);
}
}
In the Imatest .NET library, if an error occurs within one of the analysis module functions, an Exception will be thrown. If you catch the exception, then you can get more information about it by calling the ImatestLibrary.GetLastException() and ImatestLibrary.GetExceptionName() methods.
Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT .NET Library:
Try
Dim result = itLib.SFR.JSON(rootDir, imagePath, OperationMode.Separate, iniFile)
Catch ex As Exception
Dim iex As ImatestException = library.GetLastException()
Dim errorName As String = library.GetExceptionName()
If iex = ImatestException.FloatingLicenseException Then
Console.Out.WriteLine("All floating license seats are in use. Exit Imatest on another computer and try again.")
ElseIf iex = ImatestException.LicenseException Then
Console.Out.WriteLine("License Exception: {0}: {1}", errorName, ex.Message)
Else
Console.Out.WriteLine("An error has occurred:")
Console.Out.WriteLine(ex.Message)
End If
End Try
In the Imatest EXE library, if an error occurs within one of the analysis module functions, the return code from the executable will be -1 instead of 0. If you are calling the executable from a batch script, you can check what the return code was to determine if an exception occurred or not.
Here is an example of how you can test for an exception using the Imatest IT EXE Library:
sfr.exe "-1" "'C:ImatestSamplessfr_example.jpg'" "'C:Program FilesImatestv26.1ITbin'" "'C:ImatestSamplesimatest-v2.ini'" "'C:ImatestSamplesResults'"
if %ERRORLEVEL% neq 0 (
echo '*** Error calling sfr. Check output for details.'
)
In the Imatest EXE library, if an error occurs within one of the analysis module functions, the return code from the executable will be -1 instead of 0. If you are calling the executable from a batch script, you can check what the return code was to determine if an exception occurred or not.
Here is an example of how you can test for an exception using the Imatest IT EXE Library:
./run_sfr.sh "-1" "$HOME/ImatestSamples/sfr_example.jpg" "/Applications/Imatest/IT/v26.1/bin" "$HOME/ImatestSamples/imatest-v2.ini" "$HOME/ImatestSamples/Results"
if [ "$?" -ne "0" ]
echo '*** Error calling sfr. Check output for details.'
fi
Sample Code
Imatest IT ships with several example projects in C++, Objective-C (macOS only), Python, C#, and Visual Basic. You can find them in the samples folder of your IT installation, along with example images of Imatest test charts that can be used for each of IT's analysis modules.
Imatest IT for Windows also comes with a sample GUI application that demonstrates integrating the IT .NET libraries in a full-featured GUI application. Using the example images provided in the samples folder, you can experiment with the different analysis modules. It also provides a simple way to interact with the Imatest Acquisition Library. Using this app, you can quickly connect and test any of the supported image capture devices and make sure they are working, without writing any code. The full source code for this app is included in the .NET C# samples folder.The available log levels are:
Advanced Topics
Direct Read Mode and Reading RAW Images
Images can be passed directly into Imatest IT as byte arrays using Direct Read Mode. The images can be processed RGB or RAW. Direct Read Mode is generally much faster than passing in image file paths, since the data is already in memory and does not need to be read from disk. Although it does require more initial setup effort, if your application is speed-critical or high-volume, we strongly recommend using Direct Read Mode.
For detailed instructions on using Imatest IT's Direct Read Mode, see this article.
Using the Imatest Image Acquisition Library
Images can be directly acquired in your application from supported devices using the Imatest IT Acquisition Library (C, C++, and .NET only).
For more information on the C and C++ version of the Acquisition Library, see this article. For the .NET version, see this article.
Using Pass/Fail Metrics
Pass/Fail results are included in the JSON results for those modules that support it (Blemish, Colorcheck, Distortion, Multitest, SFR, SFRplus, eSFR-ISO, Random, Star, Stepchart, and Uniformity). If you have configured Pass/Fail criteria, and included the Pass/Fail file in your INI file, then the tests will be run, and the results will be included as a separate JSON object called "passfail".
For more information on implementing Pass/Fail in Imatest, see this article.
Logging Levels and Redirecting Output
By default, the Imatest IT modules print some information to the standard output or console. Logging levels control the nature of the output (to standard out and to log file) and may be selected by INI file control or from the Settings menu on the main window of Imatest Master.
If your application does not have a console, or you want to store this output in another way, it is possible to redirect the standard out and standard error outputs.
Select your preferred interface below to see detailed instructions.
To redirect output text using the Imatest C or C++ libraries, you need to use the function imatest_libraryInitializeWithHandlers(mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler) instead of imatest_libraryInitialize(), passing in two pointers to functions that will handle the "error" and "standard" outputs, respectively. The functions accept a const char* input, and return an int, which is the number of characters processed.
int stdOutHandler(const char* str)
{
// Record output
...
return strlen(str);
}
int stdErrHandler(const char* str)
{
// Record output
...
return strlen(str);
}
if (!imatest_libraryInitializeWithHandlers(stdErrHandler, stdOutHandler))
{
...
To redirect output text using the Imatest C or C++ libraries, you need to use the function imatest_libraryInitializeWithHandlers(mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler) instead of imatest_libraryInitialize(), passing in two pointers to functions that will handle the "error" and "standard" outputs, respectively. The functions accept a const char* input, and return an int, which is the number of characters processed.
int stdOutHandler(const char* str)
{
// Record output
...
return strlen(str);
}
int stdErrHandler(const char* str)
{
// Record output
...
return strlen(str);
}
if (!imatest_libraryInitializeWithHandlers(stdErrHandler, stdOutHandler))
{
...
To redirect output text using the Imatest C++ libraries in Objective-C, you need to use the function libImatestInitializeWithHandlers(mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler) instead of libImatestInitialize(), passing in two pointers to functions that will handle the "error" and "standard" outputs, respectively. The functions accept a const char* input, and return an int, which is the number of characters processed.
int stdOutHandler(const char* str)
{
// Record output
...
return strlen(str);
}
int stdErrHandler(const char* str)
{
// Record output
...
return strlen(str);
}
if (!libImatestInitializeWithHandlers(stdErrHandler, stdOutHandler))
{
...
To redirect output text using the Imatest Python library, you need to pass in StringIO objects to the ImatestLibrary() constructor, as the stdout and stderr named parameters. You can extract the contents of these objects using the getvalue() method, and should call close() on them at the end of your script.
import StringIO std_out = StringIO.StringIO() std_err = StringIO.StringIO() libImatest = ImatestLibrary(stdout=out_file, stderr=err_file) # Call library methods … print std_out.getvalue() print std_err.getvalue() std_out.close() std_err.close()
To redirect output text using the Imatest .NET library, you need to use the Console.SetOut(TextWriter writer) and Console.SetError(TextWriter writer) methods. You must call these methods before creating the Imatest.IT.Library object.
StringWriter stdOut = new StringWriter(); StringWriter stdErr = new StringWriter(); Console.SetOut(stdOut); Console.SetError(stdErr); ... string stdOutText = stdOut.ToString(); string stdErrText = stdErr.ToString(); stdOut.Close(); stdErr.Close();
To redirect output text using the Imatest .NET library, you need to use the Console.SetOut(TextWriter writer) and Console.SetError(TextWriter writer) methods. You must call these methods before creating the Imatest.IT.Library object.
Dim stdOut As New StringWriter() Dim stdErr As New StringWriter() Console.SetOut(stdout) Console.SetError(stderr) ... Dim stdOutStr As String = stdOut.ToString() Dim stdErrStr As String = stdErr.ToString() stdOut.Close() stdErr.Close()
To redirect output using the Imatest IT EXE interface, use the typical command line syntax you normally would use. For example,
sfr.exe "-1" "C:ImatestSamplessfr_example.jpg" "C:Program FilesImatestv26.1ITbin" "C:ImatestSamplesimatest-v2.ini" "C:ImatestSamplesResults" > "C:ImatestSamplesResultssfr_output.log" 2&>&1
will redirect stdout and stderr streams to "C:ImatestSamplesResultssfr_output.log".
To redirect output using the Imatest IT EXE interface, use the typical command line syntax you normally would use. For example,
./run_sfr.sh "-1" "$HOME/ImatestSamples/sfr_example.jpg" "/Applications/Imatest/IT/v26.1/bin" "$HOME/ImatestSamples/imatest-v2.ini" "$HOME/ImatestSamples/Results" > "$HOME/ImatestSamples/Results/sfr_output.log" 2&>&1
will redirect stdout and stderr streams to "$HOME/ImatestSamples/Results/sfr_output.log".
Advanced: Asynchronous Programming with Imatest IT .NET
With the Imatest IT .NET library, you can easily use write asynchronous module calls in your custom applications using the .NET Framework's async and await keywords along with Imatest IT .NET's JSONAsync() methods.
Making these simple changes can have dramatic effect on the responsiveness of applications, especially if they are GUI-based. To see the difference in action, run the Imatest IT .NET Sample Application found at C:Program FilesImatestv26.1ITsamples.NETImatestITSampleProjectImatestITSampleProject.exe and try both the Run and Run Async buttons. You will notice the application appears to freeze when using the non-async version, but is fully responsive when using the async methods.
Altering Existing Imatest IT .NET Code to be Asynchronous
There are only three changes that need to be made to convert single-threaded code into asynchronous code.:
-
- Add an async modifier to the signature in which the asynchronous code will be called.
-
- Add the await in front of the Imatest IT method call.
-
- Change the Imatest IT method call to use the new Async version.
Below is a code snippet of synchronous code making a simple call to the SFRPlus module:
protected void TestImage()
{
using (Library lib = new Library())
{
string rootDir = @"C:ImatestSamples";
string imagePath = @"C:ImatestSamplessfrplus_example.jpg";
// Call Imatest IT library with JSON output
string result = lib.SFRplus.JSON(rootDir, imagePath, OperationMode.Separate);
Console.Out.WriteLine(result);
}
}
Below is the same code that has been converted to call the SFRplus module asynchronously:
protected async void TestImage()
{
using (Library lib = new Library())
{
string rootDir = @"C:ImatestSamples";
string imagePath = @"C:ImatestSamplessfrplus_example.jpg";
// Call Imatest IT library with JSON output
string result = await lib.SFRplus.JSONAsync(rootDir, imagePath, OperationMode.Separate);
// Continue other operations that do not rely on the result value of the test
Console.Out.WriteLine(result);
}
}
Initializing the Imatest IT .NET Libraries Asynchronously
The Imatest IT .NET and Imatest Acquisition Library classes have static CreateAsync() methods that can be called using the await keyword:
public async void InitializeApplication()
{
/// Inside application initialization code
/// The await keyword will automatically start a new thread to initialize the library,
/// while code in the main thread continues to execute until the itLib object is
/// actually used.
Library itLib = await Library.CreateAsync();
/// Continue initializing the rest of the application while the background thread
/// initializes the rest of the application
...
/// The main thread will wait here until the secondary thread is completed and the
/// Library.CreateAsync() method has returned a Library object.
await itLib.SFRplus.JSONAsync(rootDir, inputFile, OperationMode.Separate);
/// At this point only the main thread is running
}
Parallel Processing
Imatest IT now allows you to analyze several different images in parallel,
using the new parallel_analyzer function.
Coming soon...
To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.
The parallel_analyzer_shell() C++ interface
The signature of the parallel_analyzer_shell() function is as follows:
parallel_analyzer_shell(int nargout, mwArray& results, const mwArray& tasks, const mwArray& iniFileName, const mwArray& runParallel, const mwArray& numWorkers);
| Parameter Name | Data Type | Description |
| nargout | int | The number of expected output arguments. This will be set to 1. |
| results | mwArray& [const char*] | The serialized JSON object array wrapped in a mwArray |
| tasks | const mwArray& [mxSTRUCT_CLASS] | The array of analysis tasks to run. For further information see below. |
| iniFileName | const mwArray& [const char*] | The path for the Imatest INI file used for analysis |
| runParallel | const mwArray& [bool] | A boolean set to true if parallel analysis is desired, otherwise set to false for serial operation. |
| numWorkers | const mwArray& [int] | The number of child processes to spawn. |
The tasks array is a mwArray of ClassID mxSTRUCT_CLASS. This data type has named fields, as with C++ structs. Each element of the task array has these fields:
input - The supplied image in the form of file path(s) or numeric array(s)
analysisID - An integer that tells IT which module to run. The allowed values are defined in the ImatestAnalysisIDs enum (see <IT installation root>libslibrarycppImatest_analysis_ids.h):
imatest::BLEMISH_ANALYSIS_ID
imatest::CHECKERBOARD_ANALYSIS_ID
imatest::COLORCHECK_ANALYSIS_ID
imatest::DISTORTION_ANALYSIS_ID
imatest::DOTPATTERN_ANALYSIS_ID
imatest::ESFRISO_ANALYSIS_ID
imatest::MULTITEST_ANALYSIS_ID
imatest::RANDOM_ANALYSIS_ID
imatest::SFR_ANALYSIS_ID
imatest::SFRPLUS_ANALYSIS_ID
imatest::SFRREG_ANALYSIS_ID
imatest::STAR_ANALYSIS_ID
imatest::UNIFORMITY_ANALYSIS_ID
imatest::WEDGE_ANALYSIS_ID
jsonMetaData - Image meta data in the form of serialized JSON object string. This field only needs to be filled when numeric arrays are being supplied.
An example of the creation of the tasks array for four image files is available in the parallel_analyzer sample project (<IT installation root>samplescppparallel_analyzermain.cpp). In this example, the tasks array is created with
mwSize numRows = 4; // There are 4 images to test
mwSize numCols = 1;
int numFields = 3;
const char* fieldNames[] = {"input", "analysisID", "jsonMetadata"};
mwArray tasks(numRows, numCols, numFields, fieldNames);
To supply values to the individual tasks, we make use of the Get(const char* fieldName, int numIndices, int index1, ...) accessor for mxSTRUCT_CLASS mwArrays:
// define the first task tasks.Get("input", 1, 1).Set(mwArray(".\sfrplus_example.jpg")); tasks.Get("analysisID", 1, 1).Set(sfrplusID); // define the second task tasks.Get("input", 1, 2).Set(mwArray(".\blemish_example.jpg")); tasks.Get("analysisID", 1, 2).Set(blemishID); //define the third task tasks.Get("input", 1, 3).Set(mwArray(".\colorcheck_example.jpg")); tasks.Get("analysisID", 1, 3).Set(colorcheckID); //define the fourth task tasks.Get("input", 1, 4).Set(mwArray(".\esfriso_example.jpg")); tasks.Get("analysisID", 1, 4).Set(esfrisoID);
It is important to note that this array is 1-indexed.
Creation of the remaining inputs is simpler; we use the mwArray contructors for scalar numeric values and strings.
mwArray iniFileName("..\Imatest_INI\imatest-v2.ini");
mwArray runParallel(true);
mwArray numWorkers(2);
Lastly, we call parallel_analyzer_shell() with the inputs.
mwArray out; parallel_analyzer_shell(1, out, tasks, iniFileName, runParallel, numWorkers);
The results will be returned in the out mwArray, which contains a JSON encoded string that can be parsed into an object array with one result object per task. Each result object has this form:
{
"data": {
"dateRun": "18-Sep-2017 10:26:59",
"ini_file_name": "C:\images\ini_file\imatest-v2.ini",
"ini_time_size": "18-Sep-2017 10:26:45 21822B MD5 = ac109f86b635bd5b4344d252969e64a7",
"version": "Imatest 5.0.0 SFRplus",
"title": "sfrplus_0123.jpg",
"image_path_name": "C:\images\sfrplus_0123.jpg",
...
},
"errorID": "",
"errorMessage": "",
"errorReport": ""
}
If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.
In addition to the parallel_analyzer sample, IT also includes a C++ sample project that implements parallel processing using the Boost.Interprocess Library (<IT installation root>samplescppCPP_parallel_test_project). More information can be found in this article.
To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.
The parallel_analyzer_shell() C++ interface
The signature of the parallel_analyzer_shell() function is as follows:
parallel_analyzer_shell(int nargout, mwArray& results, const mwArray& tasks, const mwArray& iniFileName, const mwArray& runParallel, const mwArray& numWorkers);
| Parameter Name | Data Type | Description |
| nargout | int | The number of expected output arguments. This will be set to 1. |
| results | mwArray& [const char*] | The serialized JSON object array wrapped in a mwArray |
| tasks | const mwArray& [mxSTRUCT_CLASS] | The array of analysis tasks to run. For further information see below. |
| iniFileName | const mwArray& [const char*] | The path for the Imatest INI file used for analysis |
| runParallel | const mwArray& [bool] | A boolean set to true if parallel analysis is desired, otherwise set to false for serial operation. |
| numWorkers | const mwArray& [int] | The number of child processes to spawn. |
The tasks array is a mwArray of ClassID mxSTRUCT_CLASS. This data type has named fields, as with C++ structs. Each element of the task array has these fields:
input - The supplied image in the form of file path(s) or numeric array(s)
analysisID - An integer that tells IT which module to run. The allowed values are defined in the ImatestAnalysisIDs enum (see <IT installation root>/libs/library/cpp/Imatest_analysis_ids.h):
imatest::BLEMISH_ANALYSIS_ID
imatest::CHECKERBOARD_ANALYSIS_ID
imatest::COLORCHECK_ANALYSIS_ID
imatest::DISTORTION_ANALYSIS_ID
imatest::DOTPATTERN_ANALYSIS_ID
imatest::ESFRISO_ANALYSIS_ID
imatest::MULTITEST_ANALYSIS_ID
imatest::RANDOM_ANALYSIS_ID
imatest::SFR_ANALYSIS_ID
imatest::SFRPLUS_ANALYSIS_ID
imatest::SFRREG_ANALYSIS_ID
imatest::STAR_ANALYSIS_ID
imatest::UNIFORMITY_ANALYSIS_ID
imatest::WEDGE_ANALYSIS_ID
jsonMetaData - Image meta data in the form of serialized JSON object string. This field only needs to be filled when numeric arrays are being supplied.
An example of the creation of the tasks array for four image files is available in the parallel_analyzer sample project (<IT installation root>samplescppparallel_analyzermain.cpp). In this example, the tasks array is created with
mwSize numRows = 4; // There are 4 images to test
mwSize numCols = 1;
int numFields = 3;
const char* fieldNames[] = {"input", "analysisID", "jsonMetadata"};
mwArray tasks(numRows, numCols, numFields, fieldNames);
To supply values to the individual tasks, we make use of the Get(const char* fieldName, int numIndices, int index1, …) accessor for mxSTRUCT_CLASS mwArrays:
// define the first task
tasks.Get("input", 1, 1).Set(mwArray(".\sfrplus_example.jpg"));
tasks.Get("analysisID", 1, 1).Set(sfrplusID);
// define the second task
tasks.Get("input", 1, 2).Set(mwArray(".\blemish_example.jpg"));
tasks.Get("analysisID", 1, 2).Set(blemishID);
//define the third task
tasks.Get("input", 1, 3).Set(mwArray(".\colorcheck_example.jpg"));
tasks.Get("analysisID", 1, 3).Set(colorcheckID);
//define the fourth task
tasks.Get("input", 1, 4).Set(mwArray(".\esfriso_example.jpg"));
tasks.Get("analysisID", 1, 4).Set(esfrisoID);
It is important to note that this array is 1-indexed.
Creation of the remaining inputs is simpler; we use the mwArray contructors for scalar numeric values and strings.
mwArray iniFileName("..\Imatest_INI\imatest-v2.ini");
mwArray runParallel(true);
mwArray numWorkers(2);
Lastly, we call parallel_analyzer_shell() with the inputs.
mwArray out; parallel_analyzer_shell(1, out, tasks, iniFileName, runParallel, numWorkers);
The results will be returned in the out mwArray, which contains a JSON encoded string that can be parsed into an object array with one result object per task. Each result object has this form:
{
"data": {
"dateRun": "18-Sep-2017 10:26:59",
"ini_file_name": "C:\images\ini_file\imatest-v2.ini",
"ini_time_size": "18-Sep-2017 10:26:45 21822B MD5 = ac109f86b635bd5b4344d252969e64a7",
"version": "Imatest 5.0.0 SFRplus",
"title": "sfrplus_0123.jpg",
"image_path_name": "C:\images\sfrplus_0123.jpg",
...
},
"errorID": "",
"errorMessage": "",
"errorReport": ""
}
If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.
To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.
The task file
In the stand-alone executable version of parallel_analyzer, the list of tasks is supplied in the form of a JSON encoded file. In this JSON file, the list of tasks is represented by a JSON object array, where each individual task is an object within that array. For each task the following fields need to be defined:
input - The supplied image in the form of file path(s) or numeric array(s)
analysisID - An integer that tells IT which module to run. The allowed values are defined below:
| Module | Value |
| Blemish | 1 |
| Checkerboard | 2 |
| Colorcheck | 3 |
| Distortion | 4 |
| Dotpattern | 5 |
| eSFRiso | 6 |
| Multitest | 7 |
| Random | 8 |
| SFR | 9 |
| SFRplus | 10 |
| SFRreg | 11 |
| Star | 12 |
| Uniformity | 13 |
| Wedge | 14 |
jsonMetaData - Image meta data in the form of serialized JSON object. This field only needs to be filled when numeric arrays are being supplied.
As an example, suppose that there are two files named blemish_example.jpg and sfrplus_example.jpg in the current working directory that need to be analyzed by the Blemish and SFRplus modules, respectively. The contents of this tasks file is then
[
{
"input": "blemish_example.jpg",
"analysisID": 1,
"jsonMetadata": ""
},
{
"input": "sfrplus_example.jpg",
"analysisID": 10,
"jsonMetadata": ""
}
]
The parallel_analyzer_exe interface
The signature of the parallel_analyze executable is as follows:
parallel_analyzer_exe taskFileName iniFileName runParallel numWorkers [-o|--output_filename <filename>]
The required inputs are
taskFileName: The path to the JSON task file (see the Task File section below).
iniFileName: The path to the Imatest INI file
runParallel: A boolean value that is 1 if the user wants parallel processing and 0 if serial processing is desired.
numWorkers: An integer value indicating the number of child processes to invoke for analysis. The maximum value is the number of physical cores.
with remaining optional input
-o|--output_filename<filename>: Supply the full file path for the file into which the results are saved. Note that either '-o' or '--output_filename' can be used. If this optional input is not supplied, the results are saved to a file named 'results_<current date and time>.json'.
Continuing the above example, suppose that the task file (tasks.json) from above is in our Documents folder with the two image files and our INI file (imatest-v2.ini). The call to run the two tasks in parallel on two processes would be
cd %HOMEPATH%Documents C:Program FilesImatestv26.1ITbinparallel_analyzer_exe.exe tasks.json imatest-v2.ini 1 2
The results will be saved to a JSON encoded file in the form of a JSON object array with one result object per task. Each result object has this form:
{
"data": {
"dateRun": "18-Sep-2017 10:26:59",
"ini_file_name": "C:\images\ini_file\imatest-v2.ini",
"ini_time_size": "18-Sep-2017 10:26:45 21822B MD5 = ac109f86b635bd5b4344d252969e64a7",
"version": "Imatest 5.0.0 SFRplus",
"title": "sfrplus_0123.jpg",
"image_path_name": "C:\images\sfrplus_0123.jpg",
...
},
"errorID": "",
"errorMessage": "",
"errorReport": ""
}
If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.
To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.
The task file
In the stand-alone executable version of parallel_analyzer, the list of tasks is supplied in the form of a JSON encoded file. In this JSON file, the list of tasks is represented by a JSON object array, where each individual task is an object within that array. For each task the following fields need to be defined:
input - The supplied image in the form of file path(s) or numeric array(s)
analysisID - An integer that tells IT which module to run. The allowed values are defined below:
| Module | Value |
| Blemish | 1 |
| Checkerboard | 2 |
| Colorcheck | 3 |
| Distortion | 4 |
| Dotpattern | 5 |
| eSFRiso | 6 |
| Multitest | 7 |
| Random | 8 |
| SFR | 9 |
| SFRplus | 10 |
| SFRreg | 11 |
| Star | 12 |
| Uniformity | 13 |
| Wedge | 14 |
jsonMetaData - Image meta data in the form of serialized JSON object. This field only needs to be filled when numeric arrays are being supplied.
As an example, suppose that there are two files named blemish_example.jpg and sfrplus_example.jpg in the current working directory that need to be analyzed by the Blemish and SFRplus modules, respectively. The contents of this tasks file is then
[
{
"input": "blemish_example.jpg",
"analysisID": 1,
"jsonMetadata": ""
},
{
"input": "sfrplus_example.jpg",
"analysisID": 10,
"jsonMetadata": ""
}
]
The parallel_analyzer_exe interface
The signature of the parallel_analyze executable is as follows:
./run_parallel_analyzer.sh taskFileName iniFileName runParallel numWorkers [-o|--output_filename FILENAME]
The required inputs are
taskFileName: The path to the JSON task file (see the Task File section below).
iniFileName: The path to the Imatest INI file
runParallel: A boolean value that is 1 if the user wants parallel processing and 0 if serial processing is desired.
numWorkers: An integer value indicating the number of child processes to invoke for analysis. The maximum value is the number of physical cores.
with remaining optional input
-o|--output_filename<filename>: Supply the full file path for the file into which the results are saved. Note that either '-o' or '--output_filename' can be used. If this optional input is not supplied, the results are saved to a file named 'results_<current date and time>.json'.
Continuing the above example, suppose that the task file (tasks.json) from above is in our Documents folder with the two image files and our INI file (imatest-v2.ini). The call on macOS to run the two tasks in parallel on two processes would be
cd ~/Documents /Applications/Imatest/IT/v26.1/bin/run_parallel_analyzer.sh ./tasks.json ./imatest-v2.ini 1 2
And on Linux the command would be
cd ~/Documents /usr/local/Imatest/v26.1/IT/bin/run_parallel_analyzer.sh ./tasks.json ./imatest-v2.ini 1 2
The results will be saved to a JSON encoded file in the form of a JSON object array with one result object per task. Each result object has this form:
{
"data": {
"dateRun": "18-Sep-2017 10:26:59",
"ini_file_name": "C:\images\ini_file\imatest-v2.ini",
"ini_time_size": "18-Sep-2017 10:26:45 21822B MD5 = ac109f86b635bd5b4344d252969e64a7",
"version": "Imatest 5.0.0 SFRplus",
"title": "sfrplus_0123.jpg",
"image_path_name": "C:\images\sfrplus_0123.jpg",
...
},
"errorID": "",
"errorMessage": "",
"errorReport": ""
}
If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.
Imatest IT allows you to analyze several different images in parallel, using the new parallel_analyzer function.
To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.
To create an analysis task, use the new_parallel_task function:
ImatestLibrary.new_parallel_task(image_files=None, image_data=None, analysis_type=None, image_data_meta_data=None)
| Parameter Name | Data Type | Description |
|---|---|---|
| image_files | str or list of strs | Either a file path to an image, or a list of file paths |
| image_data | str/bytes or array.array (numerical) | If you are providing raw image data, use this argument, which is either the read value of the image in str (Python 2.7) or bytes (Python 3.6, 3.7) form. If using image_data, you must include the image_data_meta_data argument, which you can get by calling ImatestLibrary.build_json_args() |
| analysis_type | enum | A flag telling Imatest IT which module to run. Valid values are constants on the ImatestLibrary class: ImatestLibrary.BLEMISH_ANALYSIS ImatestLibrary.CHECKERBOARD_ANALYSIS ImatestLibrary.COLORCHECK_ANALYSIS ImatestLibrary.DISTORTION_ANALYSIS ImatestLibrary.DOTPATTERN_ANALYSIS ImatestLibrary.ESFRISO_ANALYSIS ImatestLibrary.MULTITEST_ANALYSIS ImatestLibrary.RANDOM_ANALYSIS ImatestLibrary.SFR_ANALYSIS ImatestLibrary.SFRPLUS_ANALYSIS ImatestLibrary.SFRREG_ANALYSIS ImatestLibrary.STAR_ANALYSIS ImatestLibrary.UNIFORMITY_ANALYSIS ImatestLibrary.WEDGE_ANALYSIS |
| image_data_meta_data | dict | A dict object containing the direct read meta data, used to help interpret the raw byte data, and obtained by calling ImatestLibrary.build_json_args(). Required if using the image_data argument, not needed if using image_files. |
add each of your tasks to a list, then call ImatestLibrary.parallel_analyser, passing in the path to your INI file, True for run_parallel, and the number of worker processes you'd like to use:
ini_file = r'C:imagesini_fileimatest-v2.ini' tasks = [] tasks.append(library.new_parallel_task(image_files=r'C:imagessfrplus_0123.jpg', analysis_type=ImatestLibrary.SFRPLUS_ANALYSIS)) tasks.append(library.new_parallel_task(image_files=[r'C:imagesblemish_0001.jpg', r'C:imagesblemish_0002.jpg', r'C:imagesblemish_0003.jpg'], analysis_type=ImageLibrary.BLEMISH_ANALYSIS)) .... result = library.parallel_analyzer(tasks=tasks, ini_file=ini_file, run_parallel=True, num_workers=4)
The result will be a JSON encoded string that can be parsed into an array of result objects using json.loads(result). Each result object has this form:
{
"data": {
"dateRun": "18-Sep-2017 10:26:59",
"ini_file_name": "C:\images\ini_file\imatest-v2.ini",
"ini_time_size": "18-Sep-2017 10:26:45 21822B MD5 = ac109f86b635bd5b4344d252969e64a7",
"version": "Imatest 5.0.0 SFRplus",
"title": "sfrplus_0123.jpg",
"image_path_name": "C:\images\sfrplus_0123.jpg",
...
},
"errorID": "",
"errorMessage": "",
"errorReport": ""
}
If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property:
resultArr = json.loads(result)
for task_result in result_arr:
if task_result['errorID']:
# Gracefully handle the error
else:
result_data = task_result['data']
# Process the results in the result_data dictionary
Imatest IT allows you to analyze several different images in parallel, using the new ParallelAnalyzer.Execute() method.
To use the ParallelAnalyzer, first create a List of ImatestTasks objects that contain images to be analyzed. Each task will be assigned to a different parallel process. The number of available concurrent worker processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer workers if you need.
To create an ImatestTask, use one of the overloaded ImatestTask.Create() methods:
public static ImatestTask Create(string imageFilePath, ImatestModule module); public static ImatestTask Create(IEnumerable<string> imageFilePaths, ImatestModule module); public static ImatestTask Create(byte[] imageData, ImatestModule module, DirectReadOptions imageMetaData); public static ImatestTask Create(UInt16[] imageData, ImatestModule module, DirectReadOptions imageMetaData); public static ImatestTask Create(UInt32[] imageData, ImatestModule module, DirectReadOptions imageMetaData);
| Parameter Name | Data Type | Description |
|---|---|---|
| imageFilePath | string | A file path to an image |
| imageFilePaths | IEnumerable<string> | A collection of file paths to images |
| imageData | byte[], UInt16[], UInt32[] | Raw image data (if you are using direct read mode) |
| module | enum (ImatestLibrary) | A flag telling Imatest IT which module to run. Valid values are contained in the ImatestModule enum: ImatestModule.Blemish ImatestModule.Checkerboard ImatestModule.Colorcheck ImatestModule.Distortion ImatestModule.DotPattern ImatestModule.eSFRISO ImatestModule.Multitest ImatestModule.Random ImatestModule.SFR ImatestModule.SFRplus ImatestModule.SFRreg ImatestModule.Star ImatestModule.Uniformity ImatestModule.Wedge |
| imageMetaData | DirectReadOptions | An instance of the DirectReadOptions class that contains image meta data, used to help interpret the raw byte data. |
Add each of your tasks to a collection of type ImatestTask, then call Library.ParallelAnalyzer.Execute(), passing in the path to your INI file for iniFilePath, true for runInParallel, and the number of worker processes you'd like to use:
string inFile = "C:\images\ini_file\imatest-v2.ini";
List<ImatestTask> lstTasks = new List<ImatestTask>();
lstTasks.Add(ImatestTask.Create("C:\images\sfrplus_0123.jpg", ImatestModule.SFRplus));
lstTasks.Add(ImatestTask.Create(new List<string>() { "C:\image\blemish_0001.jpg", "C:\images\blemish_0002.jpg", "C:\images\blemish_0003.jpg" }, ImatestModule.Blemish));
....
string result = library.ParallelAnalyzer.Execute(lstTasks, iniFile, true, 2);
The result will be a JSON encoded string that can be parsed into an array of result objects using any .NET JSON library. Each result object has this form:
{
"data": {
"dateRun": "18-Sep-2017 10:26:59",
"ini_file_name": "C:\images\ini_file\imatest-v2.ini",
"ini_time_size": "18-Sep-2017 10:26:45 21822B MD5 = ac109f86b635bd5b4344d252969e64a7",
"version": "Imatest 5.0.0 SFRplus",
"title": "sfrplus_0123.jpg",
"image_path_name": "C:\images\sfrplus_0123.jpg",
...
},
"errorID": "",
"errorMessage": "",
"errorReport": ""
}
If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.
Imatest IT allows you to analyze several different images in parallel, using the new ParallelAnalyzer.Execute() method.
To use the ParallelAnalyzer, first create a List of ImatestTasks objects that contain images to be analyzed. Each task will be assigned to a different parallel process. The number of available concurrent worker processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer workers if you need.
To create an ImatestTask, use one of the overloaded ImatestTask.Create() methods:
Public Shared Function Create(imageFilePath As String, [module] As ImatestModule) As ImatestTask Public Shared Function Create(imageFilePaths As IEnumerable(Of String), [module] As ImatestModule) As ImatestTask Public Shared Function Create(imageData() As Byte, [module] As ImatestModule, imageMetaData As DirectReadOptions) As ImatestTask Public Shared Function Create(imageData() As UShort, [module] As ImatestModule, imageMetaData As DirectReadOptions) As ImatestTask Public Shared Function Create(imageData() As UInteger, [module] As ImatestModule, imageMetaData As DirectReadOptions) As ImatestTask
| Parameter Name | Data Type | Description |
|---|---|---|
| imageFilePath | string | A file path to an image |
| imageFilePaths | IEnumerable<string> | A collection of file paths to images |
| imageData | byte[], UInt16[], UInt32[] | Raw image data (if you are using direct read mode) |
| module | enum (ImatestLibrary) | A flag telling Imatest IT which module to run. Valid values are contained in the ImatestModule enum: ImatestModule.Blemish ImatestModule.Checkerboard ImatestModule.Colorcheck ImatestModule.Distortion ImatestModule.DotPattern ImatestModule.eSFRISO ImatestModule.Multitest ImatestModule.Random ImatestModule.SFR ImatestModule.SFRplus ImatestModule.SFRreg ImatestModule.Star ImatestModule.Uniformity ImatestModule.Wedge |
| imageMetaData | DirectReadOptions | An instance of the DirectReadOptions class that contains image meta data, used to help interpret the raw byte data. |
Add each of your tasks to a collection of type ImatestTask, then call Library.ParallelAnalyzer.Execute(), passing in the path to your INI file for iniFilePath, true for runInParallel, and the number of worker processes you'd like to use:
Dim iniFilePath As String
Dim lstTasks As New List(Of ImatestTask)()
Dim result As String
iniFilePath = "C:\images\ini_file\imatest-v2.ini"
lstTasks.Add(ImatestTask.Create("C:\images\sfrplus_0123.jpg", ImatestModule.SFRplus))
lstTasks.Add(ImatestTask.Create("C:\image\blemish_0001.jpg" ImatestModule.Blemish))
List<ImatestTask> lstTasks = new List<ImatestTask>();
lstTasks.Add(ImatestTask.Create("C:\images\sfrplus_0123.jpg", ImatestModule.SFRplus));
lstTasks.Add(ImatestTask.Create(new List<string>() { "C:\image\blemish_0001.jpg", "C:\images\blemish_0002.jpg", "C:\images\blemish_0003.jpg" }, ImatestModule.Blemish));
....
result = library.ParallelAnalyzer.Execute(lstTasks, iniFilePath, True, 4)
The result will be a JSON encoded string that can be parsed into an array of result objects using any .NET JSON library. Each result object has this form:
{
"data": {
"dateRun": "18-Sep-2017 10:26:59",
"ini_file_name": "C:\images\ini_file\imatest-v2.ini",
"ini_time_size": "18-Sep-2017 10:26:45 21822B MD5 = ac109f86b635bd5b4344d252969e64a7",
"version": "Imatest 5.0.0 SFRplus",
"title": "sfrplus_0123.jpg",
"image_path_name": "C:\images\sfrplus_0123.jpg",
...
},
"errorID": "",
"errorMessage": "",
"errorReport": ""
}
If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.
Arbitrary Charts Module
Imatest IT now allows you to call the Arbitrary Charts module in using the new arbitrary_charts functions. For more information on the Arbitrary Charts modules, see this article.
Coming soon...
Coming soon...
The function prototype for Arbitrary Charts is
arbitrary_charts_shell(int nargout, mwArray& output, const mwArray& inputData, const mwArray& chartFile, const mwArray& iniFile, const mwArray& averageMode, const mwArray& optionsJson)
where the parameters are defined in the following table:
nargoutintAlways set this to 1. This parameter indicates the number of desired outputs.
| Parameter Name | Data Type | Description |
|---|---|---|
| output | mwArray(const char*) | This will contains the results in the form of a JSON-encoded UTF-16 string. |
| inputData | mwArray | The input image data. This can be in the form of a single image file path, a mwArray of type mxCELL_CLASS containing multiple image paths, or a mwArray of type mxCELL_CLASS containing numeric arrays. |
| chartFile | mwArray(const char*) | The file path to the chart definition file (see /26.1/arbitrary-charts/definitions). |
| iniFile | mwArray(const char*) | The file path to the INI file. |
| averageMode | mwArray(int) || mwArray(const char*) | This parameter allows you to specify whether if groups of files are averaged (averageMode == 1) or not (averageMode == 0). |
| optionsJson | mwArray(const char*) | This parameter is a JSON-encoded string that contains descriptive meta-data for the image. See below for more information. |
To begin, declare the iniFileParam and chartFileParam variables and supply the fully-qualified paths to INI and chart definition files.
- (void)runTest: (id)param
{
@autoreleasepool {
try{
mwArray iniFileParam("/some/folder/imatest-v2.ini");
mwArray chartFileParm("/some/folder/chart_definition.json");
Next the images need to be supplied either as one or more image files, or as image data arrays. If you want to supply more than one image file at a time you will need to first construct an mwArray of type mxCELL_CLASS. For example, if you had three images inputDataParam would be constructed as follows:
mwArray inputDataParam(3, 1, mxCELL_CLASS);
inputDataParam.Get(1, 1).Set(mwArray("/some/folder/image1.jpg"));
inputDataParam.Get(1, 2).Set(mwArray("/some/folder/image2.jpg"));
inputDataParam.Get(1, 3).Set(mwArray("/some/folder/image3.jpg"));
Alternatively, if you had only a single image file, you can construct inputDataParam by passing the image file path directly to the mwArray constructor
mwArray inputDataParam("/some/folder/image.jpg");
If you are supplying more than one image, you can specify whether the images should be averaged (averageMode == 1) or analyzed separately (averageMode == 0) using the averageModeParam, which can be set to contain a numeric value or a string such as
The remaining parameter to construct is optionsJson. The JSON properties defined in the optionsJson parameter are defined in the table below.
| Option Name | Data Type | Required? | Description |
|---|---|---|---|
| width | int | image data arrays only | The width of the image in pixels. |
| height | int | image data arrays only | The height of the image in pixels. |
| encoding | string | Yes | The data encoding format of the image data. For now the options are (case-insensitive):'intensity', 'sRGB', 'adobe_rgb', 'wide_gamut_rgb', 'pro_photo_rgb', 'apple_rgb', 'colormatch', 'rec_709_full', 'rec_709_legal', 'rec_2020_full', 'rec_2020_legal', 'aces'. Use 'intensity' for 1-channel grayscale data, while the others are for standard RGB encodings. |
| fileroot | string | image data arrays only | The file path to the source image file. |
| extension | string | image data arrays only | The file extension to the source image file. |
| serial_number | string | No | A string containing the serial number. |
| part_number | string | No | A string containing the part number. |
| crop_borders | double array | No | A 1 x 4 double array indicating the crop borders ( [Left Top Right Bottom] ). |
| lens_to_chart_distance_cm | double | No | The lens to chart distance in cm. |
| chart_height_cm | double | No | The chart height in cm. |
In this example, image files are being supplied, so we are only required to supply the image encoding, for example:
mwArray optionsJsonParam("{"encoding":"sRGB"}");
Lastly, we call arbitrary_charts_shell and supply the parameters that have been constructed
// Call the library function
mwArray output
arbitrary_charts_shell(1, output, inputDataParam, chartFileParm, iniFileParam, averageModeParam, optionsJsonParam);
// Extract the JSON-encoded string.
// Note that the mwArray contains only UTF-16 strings, which we must load into an NSString
auto numel = out.NumberOfElements();
std::u16string buffer(numel+1, 0);
out.GetCharData(&buffer[0], numel);
char* data = (char*)buffer.data();
unsigned long size = buffer.size()*sizeof(char16_t);
NSString* jsonString =[[NSString alloc] initWithBytes:data length:size encoding:NSUTF16LittleEndianStringEncoding];
// Process results
} catch (mwException ex){
NSLog(@"Error");
NSLog(@"%s", ex.what());
ex.print_stack_trace();
}
}
}
The result will be a JSON-encoded string of this form:
{
"Info": {
"Timestamp": "04-Oct-2017 09:09:08",
"Version": "Imatest 5.1.0.25883 Alpha ",
"Build": "2017-10-03",
"Calculation_time_seconds": [44.36107732]
},
"Results_array_sources": "C:\images\P1858_combination_chart_example.jpg",
"Results": {
...
}
}
First, create an image options dictionary by calling ImatestLibrary.get_arbitrary_charts_options():
ImatestLibrary.get_arbitrary_charts_options(self, width=None, height=None, encoding=None, filename=None, extension=None, pixel_size=None)
| Parameter Name | Data Type | Description |
|---|---|---|
| width | int | Image width (in pixels) |
| height | int | Image height (in pixels) |
| encoding | str | The pixel encoding (i.e., "srgb", "intensity") |
| filename | str | (direct read only) The name of the file, used for results file names. |
| extension | str | (direct read only) The extension key used to decode the direct read image bytes, as configured in the Read Raw screen of Imatest Master. |
| pixel_size | enum | (direct read only) The pixel size of the direct read image. Use one of these constants: ImatestLibrary.PIXEL_SIZE_8_BIT_UNSIGNED ImatestLibrary.PIXEL_SIZE_16_BIT_UNSIGNED ImatestLibrary.PIXEL_SIZE_32_BIT_UNSIGNED |
Once you have the options object, you can then call the one of the arbitrary_charts functions:
ImatestLibrary.arbitrary_charts_separate(self, image_files=None, image_data=None, chart_file=None, ini_file=None, options=None) ImatestLibrary.arbitrary_charts_signal_average(self, image_files=None, image_data=None, chart_file=None, ini_file=None, options=None)
The arbitrary_charts_separate function will analyze multiple inputs separately, while the arbitrary_charts_signal_average function will combine two images' results into a single signal averaged result.
| Parameter Name | Data Type | Description |
|---|---|---|
| image_files | str or list of strs | Either a file path to an image, or a list of file paths |
| image_data | str/bytes or array.array (numerical) | If you are providing raw image data, use this argument, which is the read value of the image in bytes (Python 3.9, 3.10, 3.11, 3.12) form. If using image_data, you must include the required parameters into the ImatestLibrary.get_arbitrary_charts_options() method |
| chart_file | str | The path to the chart definition file. |
| ini_file | str | The path to the INI file. |
| options | dict | The dict object returned by calling ImatestLibrary.get_arbitrary_charts_options(). |
The result will be a JSON-encoded string, which can be converted to a dict using json.loads(), of this form:
{
"Info": {
"Timestamp": "04-Oct-2017 09:09:08",
"Version": "Imatest 5.1.0.25883 Alpha ",
"Build": "2017-10-03",
"Calculation_time_seconds": [44.36107732]
},
"Results_array_sources": "C:\images\P1858_combination_chart_example.jpg",
"Results": {
...
}
}
First, create an ArbitraryChartOptions object:
ArbitraryChartOptions arbChartOptions = new ArbitraryChartOptions(); arbChartOptions.Encoding = ImageEncoding.sRGB; arbChartOptions.Width = 1296; arbChartOptions.Height = 808;
| Property Name | Data Type | Description |
|---|---|---|
| Width | int | Image width (in pixels) |
| Height | int | Image height (in pixels) |
| Encoding | enum (ImageEncoding) | The pixel encoding: ImageEncoding.sRGB ImageEncoding.Intensity |
| Filename | string | (direct read only) The name of the file, used for results file names. |
| Extension | string | (direct read only) The extension key used to decode the direct read image bytes, as configured in the Read Raw screen of Imatest Master. |
Once you have the ArbitraryChartOptions object, you can then call the one of the ArbitraryCharts methods:
public string Separate(string inputFile, string chartFile, string iniFile, ArbitraryChartOptions options); public string Separate(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options); public string Separate(byte[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options); public string Separate(ushort[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options); public string Separate(uint[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options); public Task<string> SeparateAsync(string inputFile, string chartFile, string iniFile, ArbitraryChartOptions options); public Task<string> SeparateAsync(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options); public Task<string>; SeparateAsync(byte[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options); public Task<string> SeparateAsync(ushort[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options); public Task<string> SeparateAsync(uint[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options); public string SignalAverage(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options); public Task<string> SignalAverageAsync(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options);
The ArbitraryCharts.Separate methods will analyze multiple inputs separately, while the ArbitraryCharts.SignalAverage method will combine two images' results into a single signal averaged result.
| Parameter Name | Data Type | Description |
|---|---|---|
| inputFile(s) | string or IEnumberable | Either a file path to an image, or a list of file paths |
| imageData | byte[], UInt16[], UInt32[] | Raw image data (if you are using direct read mode) |
| chartFile | str | The path to the chart definition file. |
| iniFile | str | The path to the INI file. |
| options | dict | The ArbitraryChartOptions object. |
The result will be a JSON-encoded string, which can be parsed using any .NET JSON library, of this form:
{
"Info": {
"Timestamp": "04-Oct-2017 09:09:08",
"Version": "Imatest 5.1.0.25883 Alpha ",
"Build": "2017-10-03",
"Calculation_time_seconds": [44.36107732]
},
"Results_array_sources": "C:\images\P1858_combination_chart_example.jpg",
"Results": {
...
}
}
First, create an ArbitraryChartOptions object:
Dim arbChartOptions As ArbitraryChartOptions arbChartOptions = new ArbitraryChartOptions() arbChartOptions.Encoding = ImageEncoding.sRGB arbChartOptions.Width = 1296 arbChartOptions.Height = 808
| Property Name | Data Type | Description |
|---|---|---|
| Width | int | Image width (in pixels) |
| Height | int | Image height (in pixels) |
| Encoding | enum (ImageEncoding) | The pixel encoding: ImageEncoding.sRGB ImageEncoding.Intensity |
| Filename | string | (direct read only) The name of the file, used for results file names. |
| Extension | string | (direct read only) The extension key used to decode the direct read image bytes, as configured in the Read Raw screen of Imatest Master. |
Once you have the ArbitraryChartOptions object, you can then call the one of the ArbitraryCharts methods:
Public Function Separate(inputFile As String, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String Public Function Separate(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String Public Function Separate(imageData() As Byte, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String Public Function Separate(imageData() As UShort, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String Public Function Separate(imageData() As UInteger, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String Public Function SeparateAsync(inputFile As String, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String) Public Function SeparateAsync(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String) Public Function SeparateAsync(imageData() As Byte, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String) Public Function SeparateAsync(imageData() As UShort, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String) Public Function SeparateAsync(imageData() As UInteger, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String) Public Function SignalAverage(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String Public Function SignalAverageAsync(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String)
The ArbitraryCharts.Separate methods will analyze multiple inputs separately, while the ArbitraryCharts.SignalAverage method will combine two images' results into a single signal averaged result.
| Parameter Name | Data Type | Description |
|---|---|---|
| inputFile(s) | string or IEnumberable | Either a file path to an image, or a list of file paths |
| imageData | byte[], UInt16[], UInt32[] | Raw image data (if you are using direct read mode) |
| chartFile | str | The path to the chart definition file. |
| iniFile | str | The path to the INI file. |
| options | dict | The ArbitraryChartOptions object. |
The result will be a JSON-encoded string, which can be parsed using any .NET JSON library, of this form:
{
"Info": {
"Timestamp": "04-Oct-2017 09:09:08",
"Version": "Imatest 5.1.0.25883 Alpha ",
"Build": "2017-10-03",
"Calculation_time_seconds": [44.36107732]
},
"Results_array_sources": "C:\images\P1858_combination_chart_example.jpg",
"Results": {
...
}
}
The Arbitrary Charts IT/EXE module has the following command-line interface
Usage: user_defined_charts.exe inputData chartFile iniFile averageMode optionsJsonFile
Positional arguments:
inputData the image file path
chartFile the chart definition file path
iniFile the Imatest INI file path
averageMode specify whether if groups of files are averaged (averageMode == 1) or not (averageMode == 0).
optionsJsonFile the file path to a JSON-encoded file that specifies the allowed options (see below)
The optionsJsonFile input corresponds to a JSON-encoded file with the following object properties:
| Option Name | Data Type | Required? | Description |
|---|---|---|---|
| encoding | string | Yes | The data encoding format of the image data. For now the options are (case-insensitive):'intensity', 'sRGB', 'adobe_rgb', 'wide_gamut_rgb', 'pro_photo_rgb', 'apple_rgb', 'colormatch', 'rec_709_full', 'rec_709_legal', 'rec_2020_full', 'rec_2020_legal', 'aces'. Use 'intensity' for 1-channel grayscale data, while the others are for standard RGB encodings. |
| serial_number | string | No | A string containing the serial number. |
| part_number | string | No | A string containing the part number. |
| crop_borders | double array | No | A 1 x 4 double array indicating the crop borders ( [Left Top Right Bottom] ). |
| lens_to_chart_distance_cm | double | No | The lens to chart distance in cm. |
To run the Arbitrary Charts module on a single image, as an example we can analyze using the sample image and chart definition file included with the C++ Arbitrary Charts sample. The image that is used in the sample has an sRGB encode. So we produce a JSON file that we arbitrarily name "options.json" and add the following contents
{
"encoding": "sRGB"
}
We then run user_defined_charts.exe with
user_defined_charts.exe "C:Program FilesImatestv26.1ITsamplescpparbitrary_chartsP1858_combination_chart_example.jpg" "C:Program FilesImatestv26.1ITsamplescpparbitrary_chartsP1858_combination_variant.json" "C:Program FilesImatestv26.1ITsamplescppImatest_INIimatest-v2.ini" "0" "options.json"
JSON results are saved to %HOMEDRIVE%%HOMEPATH%Results by default.
The Arbitrary Charts IT/EXE module has the following command-line interface
Usage: user_defined_charts inputData chartFile iniFile averageMode optionsJsonFile
Positional arguments:
inputData the image file path
chartFile the chart definition file path
iniFile the Imatest INI file path
averageMode specify whether if groups of files are averaged (averageMode == 1) or not (averageMode == 0).
optionsJsonFile the file path to a JSON-encoded file that specifies the allowed options (see below)
The optionsJsonFile input corresponds to a JSON-encoded file with the following object properties:
| Option Name | Data Type | Required? | Description |
|---|---|---|---|
| encoding | string | Yes | The data encoding format of the image data. For now the options are (case-insensitive):'intensity', 'sRGB', 'adobe_rgb', 'wide_gamut_rgb', 'pro_photo_rgb', 'apple_rgb', 'colormatch', 'rec_709_full', 'rec_709_legal', 'rec_2020_full', 'rec_2020_legal', 'aces'. Use 'intensity' for 1-channel grayscale data, while the others are for standard RGB encodings. |
| serial_number | string | No | A string containing the serial number. |
| part_number | string | No | A string containing the part number. |
| crop_borders | double array | No | A 1 x 4 double array indicating the crop borders ( [Left Top Right Bottom] ). |
| lens_to_chart_distance_cm | double | No | The lens to chart distance in cm. |
To run the Arbitrary Charts module on a single image, as an example we can analyze using the sample image and chart definition file included with the Objective-C Arbitrary Charts sample provided for macOS, or the C++ Arbitrary Charts sample for Linux. The image that is used in the sample has an sRGB encode. So we produce a JSON file that we arbitrarily name "options.json" and add the following contents
{
"encoding": "sRGB"
}
We then execute run_user_defined_charts.sh with
./run_user_defined_charts.sh "/Applications/Imatest/IT/v26.1/samples/images/P1858_combination_chart_example.jpg" "/Applications/Imatest/IT/v26.1/samples/images/P1858_combo_variant.json" "/Applications/Imatest/IT/v26.1/samples/Objective-C/Imatest_INI/imatest-v2.ini" "0" "options.json"
JSON results are saved to $HOME/Results by default.
Concentric Rings Module
Coming soon ...
The signature of the concentric_rings_shell() function is as follows:
concentric_rings_shell(int nargout, mwArray& jsonManifest, const mwArray& imagePaths, const mwArray& iniFile);
| Parameter Name | Data Type | Description |
| nargout | int | Number of output arguments. Set to 1. |
| jsonManifest | mwArray& [const char*] | The serialized JSON object array wrapped in a mwArray |
| imagePaths | const mwArray& [const char*] | A mwArray of type mxCELL_CLASS that contains a list of image file path strings or a mwArray of type mxCHAR_CLASS for a single image file path string |
| iniFile | const mwArray& [const char*] | The path for the Imatest INI file used for analysis |
Single Image Example
For the case of a single image, it is simpler to assign the imagePaths to an mwArray of type mxCHAR_CLASS, like the following
// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\Imatest_INI\imatest-v2.ini");
mwArray imagePaths(".\concentric_rings_example.png");
mwArray jsonManifestFileList;
concentric_rings_shell(1, jsonManifestFileList, imagePaths, iniFilePath);
Multiple Images Example
For multiple images to be analyzed as a batch of separate images, the imagePaths parameter needs to be an mwArray of type mxCELL_CLASS, like as follows:
// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\Imatest_INI\imatest-v2.ini");
mwArray imagePaths(1, 2, mxCELL_CLASS);
// The mwArray::Get() accessor uses a 1-based index with a prototype of the form
// Get(num_indices, index1, ...)
imagePaths.Get(1, 1).Set(mwArray(".\concentric_rings_example_1.png"));
imagePaths.Get(1, 2).Set(mwArray(".\concentric_rings_example_2.png"));
mwArray jsonManifestFileList;
concentric_rings_shell(1, jsonManifestFileList, imagePaths, iniFilePath);
JSON Output
The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields
{
"summaryFiles": [
// A list of file paths to the summary files for this run, which contain the results and settings used
],
"plotFiles": [
// A list of file paths to plots saved for this run.
]
}
Each file in "summaryFiles" is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with "..." used to omit details for the sake of brevity.
{
"concentric_ring": {
"imatest": {
...
"ini_file": {
"filename": ...,
"md5": ..."
},
...
},
"inputs": {
"image_file": {
"filename": ...,
"md5": ...
},
"settings": {
...
}
}
},
"results": {
"regmark_data": {
...
},
"summary": {
"fov": {
...
},
"field_angle": {
...
}
},
"raw_data": {
...
}
}
}
}
The signature of the concentric_rings_shell() function is as follows:
concentric_rings_shell(int nargout, mwArray& jsonManifest, const mwArray& imagePaths, const mwArray& iniFile);
| Parameter Name | Data Type | Description |
| nargout | int | Number of output arguments. Set to 1. |
| jsonManifest | mwArray& [const char*] | The serialized JSON object array wrapped in a mwArray |
| imagePaths | const mwArray& [const char*] | A mwArray of type mxCELL_CLASS that contains a list of image file path strings or a mwArray of type mxCHAR_CLASS for a single image file path string |
| iniFile | const mwArray& [const char*] | The path for the Imatest INI file used for analysis |
Single Image Example
For the case of a single image, it is simpler to assign the imagePaths to an mwArray of type mxCHAR_CLASS, like the following:
NSString* samplesRootPath = [[[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]; NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"]; NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"]; NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"]; NSString* imageFilePath = [imageFolderPath stringByAppendingPathComponent:@"concentric_rings_example.png"]; // iniFile is the file path for the Imatest INI file mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]); // In the next example, we utilize the fileListInput parameter instead mwArray imagePathsInput([imageFilePath cStringUsingEncoding:NSASCIIStringEncoding]); mwArray jsonManifest; concentric_rings_shell(1, jsonManifest, imagePathsInput, iniFileParam);
Multiple Images Example
For multiple images to be analyzed as a batch of separate images, the imagePaths parameter needs to be an mwArray of type mxCELL_CLASS, like as follows:
NSString* samplesRootPath = [[[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]; NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"]; NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"]; NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"]; NSString* imageFilePath1 = [imageFolderPath stringByAppendingPathComponent:@"concentric_rings_example_1.png"]; NSString* imageFilePath2 = [imageFolderPath stringByAppendingPathComponent:@"concentric_rings_example_2.png"]; // iniFile is the file path for the Imatest INI file mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]); // In the next example, we utilize the imagePathsInput parameter instead mwArray imagePathsInput(1, 2, mxCELL_CLASS); // The mwArray::Get() accessor uses a 1-based index with a prototype of the form // Get(num_indices, index1, ...) imagePathsInput.Get(1, 1).Set(mwArray([imageFilePath1 cStringUsingEncoding:NSASCIIStringEncoding])); imagePathsInput.Get(1, 2).Set(mwArray([imageFilePath2 cStringUsingEncoding:NSASCIIStringEncoding])); mwArray jsonManifest; concentric_rings_shell(1, jsonManifest, imagePathsInput, iniFileParam);
JSON Output
The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields
{
"summaryFiles": [
// A list of file paths to the summary files for this run, which contain the results and settings used
],
"plotFiles": [
// A list of file paths to plots saved for this run.
]
}
Each file in "summaryFiles" is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with "..." used to omit details for the sake of brevity.
{
"concentric_ring": {
"imatest": {
...
"ini_file": {
"filename": ...,
"md5": ..."
},
...
},
"inputs": {
"image_file": {
"filename": ...,
"md5": ...
},
"settings": {
...
}
}
},
"results": {
"regmark_data": {
...
},
"summary": {
"fov": {
...
},
"field_angle": {
...
}
},
"raw_data": {
...
}
}
}
}
Concentric Ring analysis is accomplished using one of the following overloaded methods in Imatest.IT.Library.ConcentricRings:
string JSON(string iniFilePath, string[] imageFilePaths) string JSON(string iniFilePath, string imageFilePath) async Task<string> JSONAsync(string iniFilePath, string[] imageFilePaths) async Task<string> JSONAsync(string iniFilePath, string imageFilePath)
Example
Below is an example Concentric Rings analysis with exception handling details omitted with "..." for the sake of brevity.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Imatest.IT;
namespace Imatest.IT.Samples.ConcentricRings
{
class Program
{
/*
* This code will execute the Imatest Concentric Rings function on the file
* 'concentric_rings_example.png' which should be a capture of a concentric rings test chart.
*
* */
public const string EXAMPLE_IMAGE = "concentric_rings_example.png";
static void Main(string[] args)
{
using (Library lib = new Library())
{
try
{
DirectoryInfo currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
string rootDir = currentDirectory.Parent.Parent.Parent.FullName;
string iniFilePath = Path.Combine(rootDir, "imatest-v2.ini");
// C:Program FilesImatestv26.1ITsamplesimages
string sampleImagesDir = Path.Combine(currentDirectory.Parent.Parent.Parent.Parent.Parent.Parent.FullName, "images");
List<string> imagePaths = new List<string> {
Path.Combine(sampleImagesDir, EXAMPLE_IMAGE),
};
// Call Imatest IT library with JSON output
string jsonManifestFileList = lib.ConcentricRings.JSON(iniFilePath, imagePaths.ToArray());
Console.Out.WriteLine(result);
}
catch (Exception ex)
{
...
}
}
Console.Out.WriteLine("Press enter to exit...");
Console.In.Read();
}
}
}
JSON Output
The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields
{
"summaryFiles": [
// A list of file paths to the summary files for this run, which contain the results and settings used
],
"plotFiles": [
// A list of file paths to plots saved for this run.
]
}
Each file in "summaryFiles" is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with "..." used to omit details for the sake of brevity.
{
"concentric_ring": {
"imatest": {
...
"ini_file": {
"filename": ...,
"md5": ..."
},
...
},
"inputs": {
"image_file": {
"filename": ...,
"md5": ...
},
"settings": {
...
}
}
},
"results": {
"regmark_data": {
...
},
"summary": {
"fov": {
...
},
"field_angle": {
...
}
},
"raw_data": {
...
}
}
}
}
Concentric Ring analysis is accomplished using one of the following overloaded methods in Imatest.IT.Library.ConcentricRings:
JSON(iniFilePath as String, imageFilePaths as String()) as String string JSON(iniFilePath as String, string imageFilePath as String) as String <Awaitable> JSONAsync(iniFilePath as String, string[] imageFilePaths) as Task(Of String) <Awaitable> JSONAsync(iniFilePath as String, imageFilePath as String) as Task(Of String)
Example
Below is an example Concentric Rings analysis with exception handling details omitted with "…" for the sake of brevity.
Imports System.IO
Imports Imatest.IT
Module Program
' In this example program, the image files should be located
' in the same directory as this example script, and the 'imatest-v2.ini' file
' should be located in the "ini_file" directory in the Python samples directory.
'
' Certain diagnostic lines are written to standard out for diag.
'
Public Const EXAMPLE_IMAGE As String = "concentric_rings_example.png"
Public Sub Main()
Using library = New Library()
Try
Dim currentDirectory As DirectoryInfo
Dim rootDir As String
Dim iniFilePath As String
Dim sampleImagesDir As String
Dim jsonManifestFileList As String
Dim imagePaths(1) As String
currentDirectory = New DirectoryInfo(Directory.GetCurrentDirectory())
rootDir = currentDirectory.Parent.Parent.Parent.FullName
iniFilePath = Path.Combine(rootDir, "imatest-v2.ini")
' C:Program FilesImatestv26.1ITsamplesimages
sampleImagesDir = Path.Combine(currentDirectory.Parent.Parent.Parent.Parent.Parent.Parent.FullName, "images")
imagePaths(0) = Path.Combine(sampleImagesDir, EXAMPLE_IMAGE)
' Call Imatest IT library with JSON output
jsonManifestFileList = library.ConcentricRings.JSON(iniFilePath, imagePaths)
Console.Out.WriteLine(result)
Catch ex As Exception
...
End Try
End Using
Console.Out.WriteLine("Press enter to exit...")
Console.In.Read()
End Sub
End Module
JSON Output
The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields
{
"summaryFiles": [
// A list of file paths to the summary files for this run, which contain the results and settings used
],
"plotFiles": [
// A list of file paths to plots saved for this run.
]
}
Each file in "summaryFiles" is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with "..." used to omit details for the sake of brevity.
{
"concentric_ring": {
"imatest": {
...
"ini_file": {
"filename": ...,
"md5": ..."
},
...
},
"inputs": {
"image_file": {
"filename": ...,
"md5": ...
},
"settings": {
...
}
}
},
"results": {
"regmark_data": {
...
},
"summary": {
"fov": {
...
},
"field_angle": {
...
}
},
"raw_data": {
...
}
}
}
}
Concentric Rings IT/EXE has the following command line interface:
Concentric Rings IT/EXE
Usage: concentric_rings_exe [OPTIONS] ini-file image-paths...
Positionals:
ini-file TEXT REQUIRED The path to the Imatest INI file.
image-paths TEXT ... REQUIRED
One or more image file paths
Options:
-h,--help Print this help message and exit
-v,--version Display program version information and exit
--echo-result-manifest After a successful run, echo the result manifest json to stdout.
Example
concentric_rings_exe "pathtoimatest-v2.ini" "anotherpathmy_image.jpg"
Concentric Rings IT/EXE has the following command line interface:
Concentric Rings IT/EXE
Usage: concentric_rings_exe [OPTIONS] ini-file image-paths...
Positionals:
ini-file TEXT REQUIRED The path to the Imatest INI file.
image-paths TEXT ... REQUIRED
One or more image file paths
Options:
-h,--help Print this help message and exit
-v,--version Display program version information and exit
--echo-result-manifest After a successful run, echo the result manifest json to stdout.
Example
./run_concentric_rings_exe.sh "path/to/imatest-v2.ini" "another/path/to/my_image.jpg"
Stray Light Module
Coming soon…
The signature of the stray_light_shell() function is as follows:
stray_light_shell(int nargout, mwArray& jsonManifest, const mwArray& iniFilePath, const mwArray& configInput, const mwArray& fileListInput)
| Parameter Name | Data Type | Description |
| nargout | int | The number of expected output arguments. This will be set to 1. |
| jsonManifest | mwArray& [const char*] | The serialized JSON object array wrapped in a mwArray |
| iniFilePath | const mwArray& [const char*] | The path for the Imatest INI file used for analysis |
| configInput | const mwArray& [const char*] | An mwArray containing either a file path to a Stray Light config file (*.slconfig), or a Stray Light config in the form of a JSON-encoded string |
| fileListInput | const mwArray& [const char*] | A mwArray of type mxCELL_CLASS that contains a list of image file path strings |
The stray_light_shell() function has two mutually exclusive use cases:
-
- Input only a list of file paths via the fileListInput parameter, with configInput left an empty mwArray. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
-
- Construct an imatest::stray_light::Config object and pass it in through the configInput parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.
File list input example
In the example below, we set up a Stray Light analysis and supply only a list of files (see the Stray Light C++ sample for more details). Each file is assumed to be of a separate capture condition in this analysis.
// In the next example, we utilize the fileListInput parameter instead (and leave the ConfigInput parameter empty).
// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\Imatest_INI\imatest-v2.ini");
mwArray fileListInput(4, 1, mxCELL_CLASS);
// The mwArray::Get() accessor uses a 1-based index with a prototype of the form
// Get(num_indices, index1, ...)
fileListInput.Get(1, 1).Set(mwArray(".\cap031_Az_90_Fa_0.png"));
fileListInput.Get(1, 2).Set(mwArray(".\cap039_Az_90_Fa_8.png"));
fileListInput.Get(1, 3).Set(mwArray(".\cap058_Az_90_Fa_27.png"));
fileListInput.Get(1, 4).Set(mwArray(".\cap061_Az_90_Fa_30.png"));
// Call the library function
mwArray jsonManifest;
stray_light_shell(1, jsonManifest, iniFilePath, mwArray(), fileListInput);
When stray_light_shell() completes, the results are returned in the jsonManifest mwArray as a JSON-encoded string. By default, this JSON object is structured as follows:
{
"masks": [
// ... file paths to saved masks ...
],
"metric_images" : [
// ... file paths to saved metric images ...
],
"plots" : [
// ... file paths to saved plots ...
],
"videos" : [
// ... file paths to saved videos ...
],
"results" : [
// ... file paths to saved results files ...
]
}
where each field in the JSON object contains an array of path strings.
Config input example
The next example (also borrowed from the Stray Light C++ sample) make use of the Config and CaptureConfig defined in the imatest::stray_light namespace (see StrayLightConfig.h/.cpp and StrayLightCaptureConfig.h/.cpp included in <IT install root>/libs/library/cpp).
using imatest::stray_light::Config;
using imatest::stray_light::CaptureConfig;
// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\Imatest_INI\imatest-v2.ini");
// First we construct a imatest::stray_light::Config.
// In this example we have 4 images taken with the following capture conditions:
// ".\cap031_Az_90_Fa_0.png":
// source field angle: 0 degrees
// source azimuth angle: 90 degrees
// ".\cap039_Az_90_Fa_8.png":
// source field angle: 8 degrees
// source azimuth angle: 90 degrees
// ".\cap058_Az_90_Fa_27.png":
// source field angle: 27 degrees
// source azimuth angle: 90 degrees
// ".\cap061_Az_90_Fa_30.png":
// source field angle: 30 degrees
// source azimuth angle: 90 degrees
Config config;
config.runName = "Test run";
config.comment = "Test run within the Imatest IT sample for Stray Light";
config.captures.emplace_back(CaptureConfig({ ".\cap031_Az_90_Fa_0.png" }, 0, 90, "On-Axis"));
config.captures.emplace_back(CaptureConfig({ ".\cap039_Az_90_Fa_8.png" }, 8, 90, "Mid-Field"));
config.captures.emplace_back(CaptureConfig({ ".\cap058_Az_90_Fa_27.png" }, 27, 90, "Edge Of FOV"));
config.captures.emplace_back(CaptureConfig({ ".\cap061_Az_90_Fa_30.png" }, 30, 90, "Out Of FOV"));
mwArray configInput(config);
// Call the library function
mwArray jsonManifest;
stray_light_shell(1, jsonManifest, iniFilePath, configInput, mwArray());
with the results returned as JSON encoded string within the jsonManifest mwArray, as before.
The signature of the stray_light_shell() function is as follows:
stray_light_shell(int nargout, mwArray& jsonManifest, const mwArray& iniFilePath, const mwArray& configInput, const mwArray& fileListInput)
| Parameter Name | Data Type | Description |
| nargout | int | The number of expected output arguments. This will be set to 1. |
| jsonManifest | mwArray& [const char*] | The serialized JSON object array wrapped in a mwArray |
| iniFilePath | const mwArray& [const char*] | The path for the Imatest INI file used for analysis |
| configInput | const mwArray& [const char*] | An mwArray containing either a file path to a Stray Light config file (*.slconfig), or a Stray Light config in the form of a JSON-encoded string |
| fileListInput | const mwArray& [int] | A mwArray of type mxCELL_CLASS that contains a list of image file path strings |
The stray_light_shell() function has two mutually exclusive use cases:
-
- Input only a list of file paths via the fileListInput parameter, with configInput left an empty mwArray. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
-
- Construct an imatest::stray_light::Config object and pass it in through the configInput parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.
File list input example
In the example below, we set up a Stray Light analysis and supply only a list of files (see the Stray Light Objective-C sample for more details). Each file is assumed to be of a separate capture condition in this analysis.
// In the next example, we utilize the fileListInput parameter instead (and leave the ConfigInput parameter empty). NSString* samplesRootPath = [[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]; NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"]; NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"]; NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"]; NSString* imageFilePath1 = [imageFolderPath stringByAppendingPathComponent:@"cap031_Az_90_Fa_0.png"]; NSString* imageFilePath2 = [imageFolderPath stringByAppendingPathComponent:@"cap039_Az_90_Fa_8.png"]; NSString* imageFilePath3 = [imageFolderPath stringByAppendingPathComponent:@"cap058_Az_90_Fa_27.png"]; NSString* imageFilePath4 = [imageFolderPath stringByAppendingPathComponent:@"cap061_Az_90_Fa_30.png"]; // iniFile is the file path for the Imatest INI file mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]); mwArray fileListInput(4, 1, mxCELL_CLASS); // The mwArray::Get() accessor uses a 1-based index with a prototype of the form // Get(num_indices, index1, ...) fileListInput.Get(1, 1).Set(mwArray([imageFilePath1 cStringUsingEncoding:NSASCIIStringEncoding])); fileListInput.Get(1, 2).Set(mwArray([imageFilePath2 cStringUsingEncoding:NSASCIIStringEncoding])); fileListInput.Get(1, 3).Set(mwArray([imageFilePath3 cStringUsingEncoding:NSASCIIStringEncoding])); fileListInput.Get(1, 4).Set(mwArray([imageFilePath4 cStringUsingEncoding:NSASCIIStringEncoding])); // Call the library function mwArray jsonManifest; stray_light_shell(1, jsonManifest, iniFilePath, mwArray(), fileListInput);
When stray_light_shell() completes, the results are returned in the jsonManifest mwArray as a JSON-encoded string. By default, this JSON object is structured as follows:
{
"masks": [
// ... file paths to saved masks ...
],
"metric_images" : [
// ... file paths to saved metric images ...
],
"plots" : [
// ... file paths to saved plots ...
],
"videos" : [
// ... file paths to saved videos ...
],
"results" : [
// ... file paths to saved results files ...
]
}
where each field in the JSON object contains an array of path strings.
Config input example
The next example (also borrowed from the Stray Light C++ sample) make use of the Config and CaptureConfig defined in the imatest::stray_light namespace (see StrayLightConfig.h/.cpp and StrayLightCaptureConfig.h/.cpp included in <IT install root>/libs/library/cpp).
NSString* samplesRootPath = [[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"];
NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"];
NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"]; NSString* imageFilePath1 = [imageFolderPath stringByAppendingPathComponent:@"cap031_Az_90_Fa_0.png"];
NSString* imageFilePath2 = [imageFolderPath stringByAppendingPathComponent:@"cap039_Az_90_Fa_8.png"];
NSString* imageFilePath3 = [imageFolderPath stringByAppendingPathComponent:@"cap058_Az_90_Fa_27.png"];
NSString* imageFilePath4 = [imageFolderPath stringByAppendingPathComponent:@"cap061_Az_90_Fa_30.png"];
// iniFile is the file path for the Imatest INI file
mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]);
// First we construct a imatest::stray_light::Config.
// In this example we have 4 images taken with the following capture conditions:
// "cap031_Az_90_Fa_0.png":
// source field angle: 0 degrees
// source azimuth angle: 90 degrees
// "cap039_Az_90_Fa_8.png":
// source field angle: 8 degrees
// source azimuth angle: 90 degrees
// "cap058_Az_90_Fa_27.png":
// source field angle: 27 degrees
// source azimuth angle: 90 degrees
// "cap061_Az_90_Fa_30.png":
// source field angle: 30 degrees
// source azimuth angle: 90 degrees
imatest::stray_light::Config config;
config.runName = "Test run";
config.comment = "Test run within the Imatest IT sample for Stray Light";
config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath1 cStringUsingEncoding:NSASCIIStringEncoding] }, 0, 90, "On-Axis"));
config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath2 cStringUsingEncoding:NSASCIIStringEncoding] }, 8, 90, "Mid-Field"));
config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath3 cStringUsingEncoding:NSASCIIStringEncoding] }, 27, 90, "Edge Of FOV"));
config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath4 cStringUsingEncoding:NSASCIIStringEncoding] }, 30, 90, "Out Of FOV"));
mwArray configInputParam(config); // Call the library function
mwArray jsonManifest;
stray_light_shell(1, jsonManifest, iniFileParam, configInputParam, mwArray());
with the results returned as JSON encoded string within the jsonManifest mwArray, as before.
Stray light analysis can proceed a few different ways depending on what additional testing condition data is available.
-
- Input only a list of file paths via the fileList input parameter. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
-
- Construct an StrayLightConfig object and pass it in through the config input parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.
-
- Provide a file path to a serialized StrayLightConfig (i.e. a JSON-encoded file with the extension *.slconf).
The StrayLightConfig class has the following properties:
| Property Name | Data Type | Description |
| Captures | IEnumerable<StrayLightCaptureConfig> | The collection of captures used for this analysis. |
| RunName | string | An optional run name to assign to this analysis. |
| Comment | string | An optional comment about the configuration, test setup, etc. |
, where the StrayLightCaptureConfig class has the properties
| Property Name | Data Type | Description |
| ImagePaths | IEnumerable<string> | The collection of image file paths all taken at this source field angle and source azimuth angle. |
| SourceFieldAngleDeg | double | The source field angle in degrees. |
| SourceAzimuthAngleDeg | double | The source azimuth angle in degrees. |
| Comment | string | An optional comment for this collection of images. |
Depending on the input data source, analysis can then proceed via one of the overloaded methods in the Imatest.IT.Library.StrayLight library methods:
string Batch(string iniFilePath, StrayLightConfig config) async Task<string> BatchAsync(string iniFilePath, StrayLightConfig config) string Batch(string iniFilePath, string configFilePath) async Task<string> BatchAsync(string iniFilePath, string configFilePath) string Batch(string iniFilePath, String[] fileList) async Task<string> BatchAsync(string iniFilePath, String[] fileList)
To demonstrate the functionality, below we walk through an example (which is largely identical to the example installed at <IT install root>/samples/.NET/C#/StrayLight, but with details omitted with ... for brevity). To set up the analysis we initiate an Imatest.IT.Library instance and define the Imatest INI and image file paths.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks;
using MathWorks.MATLAB.NET.Arrays;
using Imatest.IT;
class Program
{
public const string EXAMPLE_IMAGE_1 = "cap031_Az_90_Fa_0.png";
public const string EXAMPLE_IMAGE_2 = "cap039_Az_90_Fa_8.png";
public const string EXAMPLE_IMAGE_3 = "cap058_Az_90_Fa_27.png";
public const string EXAMPLE_IMAGE_4 = "cap061_Az_90_Fa_30.png";
static void Main(string[] args)
{
using (Library lib = new Library())
{
try
{
DirectoryInfo currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
string rootDir = ... ;
string iniFilePath = Path.Combine(rootDir, "imatest-v2.ini");
string sampleImagesDir = ... ;
List<string> imagePaths = new List<string> {
Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_1),
Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_2),
Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_3),
Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_4)
};
next we construct a List<StrayLightCaptureConfig> from the image file paths
List<StrayLightCaptureConfig> captureConfigs = new List<StrayLightCaptureConfig>();
foreach (string imagePath in imagePaths) {
captureConfigs.Add(new StrayLightCaptureConfig(new List<string> { imagePath }));
}
and then construct a StrayLightConfig instance from the List<StrayLightCaptureConfig>.
StrayLightConfig config = new StrayLightConfig(captureConfigs);
Lastly we supply the StrayLightConfig instance and the INI file path to Imatest.IT.StrayLight.Batch() and execute
// Call Imatest IT library with JSON output
string result = lib.StrayLight.Batch(iniFilePath, config);
Console.Out.WriteLine(result);
}
catch (Exception ex)
{
...
}
}
}
}
Imatest.IT.StrayLight.Batch() will return a JSON-encoded string of the form
{
"masks": [
// ... file paths to saved masks ...
],
"metric_images" : [
// ... file paths to saved metric images ...
],
"plots" : [
// ... file paths to saved plots ...
],
"videos" : [
// ... file paths to saved videos ...
],
"results" : [
// ... file paths to saved results files ...
]
}
which lists the file paths of any file produced by the analysis.
Stray light analysis can proceed a few different ways depending on what additional testing condition data is available.
-
- Input only a list of file paths via the fileList input parameter. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
-
- Construct an StrayLightConfig object and pass it in through the config input parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.
-
- Provide a file path to a serialized StrayLightConfig (i.e. a JSON-encoded file with the extension *.slconf).
The StrayLightConfig class has the following properties:
| Property Name | Data Type | Description |
| Captures | IEnumerable<StrayLightCaptureConfig> | The collection of captures used for this analysis. |
| RunName | string | An optional run name to assign to this analysis. |
| Comment | string | An optional comment about the configuration, test setup, etc. |
, where the StrayLightCaptureConfig class has the properties
| Property Name | Data Type | Description |
| ImagePaths | IEnumerable<string> | The collection of image file paths all taken at this source field angle and source azimuth angle. |
| SourceFieldAngleDeg | double | The source field angle in degrees. |
| SourceAzimuthAngleDeg | double | The source azimuth angle in degrees. |
| Comment | string | An optional comment for this collection of images. |
Depending on the input data source, analysis can then proceed via one of the overloaded methods in the Imatest.IT.Library.StrayLight library methods:
Public Function Batch(iniFilePath as String, config as StrayLightConfig) as String Public Function BatchAsync(iniFilePath as String, config as StrayLightConfig) As Task(Of String) Public Function Batch(iniFilePath as String, configFilePath as String) as String Public Function BatchAsync(iniFilePath as String, configFilePath as String) As Task(Of String) Public Function Batch(string iniFilePath, fileList as String()) as String Public Function BatchAsync(iniFilePath as String, fileList as String()) As Task(Of String)
To demonstrate the functionality, below we walk through an example (which is largely identical to the example installed at <IT install root>/samples/.NET/VB.NET/StrayLight, but with details omitted with ... for brevity). To set up the analysis we initiate an Imatest.IT.Library instance, declare needed variables, and define the Imatest INI and image file paths.
Imports System.IO
Imports Imatest.IT
Module Program
Public Const EXAMPLE_IMAGE_1 As String = "cap031_Az_90_Fa_0.png"
Public Const EXAMPLE_IMAGE_2 As String = "cap039_Az_90_Fa_8.png"
Public Const EXAMPLE_IMAGE_3 As String = "cap058_Az_90_Fa_27.png"
Public Const EXAMPLE_IMAGE_4 As String = "cap061_Az_90_Fa_30.png"
Public Sub Main()
Using library = New Library()
Try
Dim currentDirectory As DirectoryInfo
Dim rootDir As String
Dim iniFilePath As String
Dim sampleImagesDir As String
Dim result As String
Dim captureConfigs(3) As StrayLightCaptureConfig
Dim captureConfig As StrayLightConfig
rootDir = ...
iniFilePath = Path.Combine(rootDir, "imatest-v2.ini")
sampleImagesDir = ...
next we construct the StrayLightCaptureConfig array from the image file paths
captureConfigs(0) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_1)})
captureConfigs(1) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_2)})
captureConfigs(2) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_3)})
captureConfigs(3) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_4)})
and then construct a StrayLightConfig instance from the List<StrayLightCaptureConfig>.
captureConfig = New StrayLightConfig(captureConfigs)
Lastly we supply the StrayLightConfig instance and the INI file path to Imatest.IT.StrayLight.Batch() and execute
' Call Imatest IT library with JSON output without Stray Light Config values
result = library.StrayLight.Batch(iniFilePath, captureConfig)
Catch ex As Exception
...
End Try
End Using
End Sub
End Module
Imatest.IT.StrayLight.Batch() will return a JSON-encoded string of the form
{
"masks": [
// ... file paths to saved masks ...
],
"metric_images" : [
// ... file paths to saved metric images ...
],
"plots" : [
// ... file paths to saved plots ...
],
"videos" : [
// ... file paths to saved videos ...
],
"results" : [
// ... file paths to saved results files ...
]
}
which lists the file paths of any file produced by the analysis.
The Stray Light IT/EXE module has the following command-line interface
stray_light_exe --help Usage: stray_light_exe [--echo-result-manifest] [--help] iniFilePath [configFilePath] [imageFileList] Analyze stray light images via the stray light module Positional arguments: iniFilePath The full path to the INI file. configFilePath The full path to the analysis config file. imageFileList The full path to all image files to analyze. Options: --echo-result-manifest After a successful run, echo the result manifest json to stdout. -h, --help Display this help information.
The Stray Light IT/EXE interface has two mutually exclusive use cases:
-
- Input only a list of file paths via the
imageFileListparameter, withconfigFilePathleft an empty string. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
- Input only a list of file paths via the
-
- Supply a file path to an *.slconf file, which provides a means to input source field angles and azimuth angles associated with each input image file. *.slconf are a JSON encoded file that can be generated from a StrayLightConfig object in the IT/Python interface, or the equivalent class in the C++, C# or VB.NET interfaces. This *.slconf file provides more information to the Stray Light module and thus a richer analysis.
To execute stray_light_shell.exe, supply the require filed paths as below
stray_light_exe.exe "imatest-v2.ini" "my_capture.slconf"
The Stray Light IT/EXE module has the following command-line interface
stray_light_exe --help Usage: stray_light_exe [--echo-result-manifest] [--help] iniFilePath [configFilePath] [imageFileList] Analyze stray light images via the stray light module Positional arguments: iniFilePath The full path to the INI file. configFilePath The full path to the analysis config file. imageFileList The full path to all image files to analyze. Options: --echo-result-manifest After a successful run, echo the result manifest json to stdout. -h, --help Display this help information.
The Stray Light IT/EXE interface has two mutually exclusive use cases:
-
- Input only a list of file paths via the
imageFileListparameter, withconfigFilePathleft an empty string. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
- Input only a list of file paths via the
-
- Supply a file path to an *.slconf file, which provides a means to input source field angles and azimuth angles associated with each input image file. *.slconf are a JSON encoded file that can be generated from a StrayLightConfig object in the IT/Python interface, or the equivalent class in the C++, C# or VB.NET interfaces. This *.slconf file provides more information to the Stray Light module and thus a richer analysis.
To execute stray_light_shell.exe, supply the require filed paths as below
./run_stray_light_exe.sh "imatest-v2.ini" "my_capture.slconf"
Troubleshooting
[kb_block category_id=22 showposts=30]2