(19)【発行国】日本国特許庁(JP)
(12)【公報種別】公表特許公報(A)
(11)【公表番号】
(43)【公表日】2024-09-18
(54)【発明の名称】ラジオミクスシステム及び方法
(51)【国際特許分類】
A61B 6/00 20240101AFI20240910BHJP
G06T 1/00 20060101ALI20240910BHJP
G06T 5/00 20240101ALI20240910BHJP
G06T 7/00 20170101ALI20240910BHJP
【FI】
A61B6/00 550D
A61B6/00 550Z
G06T1/00 290Z
G06T5/00
G06T7/00 612
【審査請求】未請求
【予備審査請求】未請求
(21)【出願番号】P 2024534133
(86)(22)【出願日】2022-08-09
(85)【翻訳文提出日】2024-04-15
(86)【国際出願番号】 US2022074701
(87)【国際公開番号】W WO2023019132
(87)【国際公開日】2023-02-16
(32)【優先日】2021-08-12
(33)【優先権主張国・地域又は機関】US
(32)【優先日】2021-08-10
(33)【優先権主張国・地域又は機関】US
(81)【指定国・地域】
【公序良俗違反の表示】
(特許庁注:以下のものは登録商標)
(71)【出願人】
【識別番号】524057957
【氏名又は名称】ディープルック・インコーポレイテッド
【氏名又は名称原語表記】DEEPLOOK,INC.
【住所又は居所原語表記】1220 Burton St.,Silver Spring,MD 20910 U.S.A.
(74)【代理人】
【識別番号】110000523
【氏名又は名称】アクシス国際弁理士法人
(72)【発明者】
【氏名】ケネス・ブーランジェ
【テーマコード(参考)】
4C093
5B057
5L096
【Fターム(参考)】
4C093AA11
4C093AA26
4C093CA18
4C093CA35
4C093DA06
4C093FD03
4C093FF17
4C093FF19
4C093FF22
4C093FF28
5B057AA07
5B057CE03
5B057DC03
5B057DC16
5L096BA06
5L096BA13
5L096DA04
5L096EA12
5L096FA02
5L096FA06
5L096FA52
5L096FA64
5L096FA66
5L096FA69
5L096FA70
5L096GA51
(57)【要約】
本発明は、X線及び他の医療用画像データから生成された画像の強調表示及びそこから生成されるラジオミクスを提供するデジタル画像処理のためのシステム、装置及び方法を提供する。
このようなシステム、装置及び方法は、
そのデータを取り込んで使用し、例えば、人間の視覚のスペクトル内及びそれを超えるグレースケールの明瞭なグラデーションを特定し、
グラデーションの範囲に基づいて境界を画定し、画定された内部輪郭及び外側の境界を有する不規則なマルチレイヤー視覚オブジェクトを形成し、そして、
画定された層を強調し、及び、強調表示を元の画像の対応する領域の上に重ね合わせ、及び/又は、元の画像の対応する領域の放射線学的測定値を決定し、
それによって、人間の視覚から以前は不明瞭であった、隠されていた、又は「マスクされた」腫瘤の潜在的な形態を明らかにする。
【特許請求の範囲】
【請求項1】
ラジオミクス-スピキュレーションの定量化/特性評価
方法であって、
A.医療用画像の形状の周囲を歩いて(walking)、その周囲を定義する座標のリストを生成するステップ、
B.前記リストを、前記周囲の変曲点によって分割された座標のグループに分けるステップ、
C.座標の各グループについて、スパン対長さの比率を決定するステップ、ここで、スパンとは、各前記グループの端点間のデカルト座標系上の距離を指し、長さとは、各前記グループによって定義される経路に沿って移動して測定された距離の合計を指す、
D.選択されたスパン対長さの比率を有するグループが前記周囲の長さを構成するそれぞれの割合を決定するステップと、そして、
E.前記医療用画像を強調すること、又は前記医療用画像に撮像された組織の形態をそれぞれのパーセンテージの関数として特定することのいずれかのステップと、
を含む、方法。
【請求項2】
請求項1に記載の方法であって、前記スパン対長さの比率が0より大きく1以下であり、直線セグメントを画定するグループは1のスパン対長さの比率を有し、直線から逸脱するグループはより小さいそのような比率を有することを特徴とする方法。
【請求項3】
請求項1記載の方法であって、ステップ(D)が以下を含む、方法:
i.前記グループをそれぞれのスパン対長さの比率にしたがってビニング(binning)し、並びに、
各ビンについて
(a)そのビンに含まれる前記グループの長さを合計し、及び、
(b)その合計が前記形状の前記周囲の長さの合計の何パーセントを占めるかを決定する。
【請求項4】
請求項3記載の方法であって、ステップ(D)が以下を含む、方法:
ii.ステップ(D)(i)(b)で生成された前記パーセンテージを、パーセンテージが決定された前記ビンの前記スパン対長さの比率に基づいてスーパービンにビニングする。
【請求項5】
請求項4に記載の方法であって、ステップ(D)が以下を含む、方法:
iii.ステップ(D)(ii)でビニングされた少なくとも選択されたパーセンテージを合計する。
【請求項6】
請求項1に記載の方法であって、ステップ(E)が以下を含む、方法:
それぞれのパーセンテージを、既知の形態の組織について決定された対応するパーセンテージと比較する。
【請求項7】
請求項6に記載の方法であって、ステップ(E)が以下を含む、方法:
形状をその形態であると特徴付けることにより、好ましい比較に応答する。
【請求項8】
請求項7に記載の方法であって、ステップ(E)が以下を含む、方法:
1つ又は複数のパーセンテージの値の範囲を使用して前記比較を実行する。
【請求項9】
請求項1に記載の方法であって、ステップ(D)が以下を含む、方法:
0.6~0.7、0.7~0.8、0.8~0.9及び0.9~1.0のうち少なくとも1つのスパン対長さの比率を有するグループが前記周囲の長さを構成するそれぞれの割合を決定する。
【請求項10】
請求項1に記載の方法であって、ステップ(D)が以下を含む、方法:
0.6~0.7、0.7~0.8、0.8~0.9及び0.9~1.0のうち少なくとも2つのスパン対長さの比率を有するグループが前記周囲の長さを構成するそれぞれの割合を決定する。
【請求項11】
請求項1に記載の方法であって、ステップ(D)が以下を含む、方法:
0.6~0.7、0.7~0.8、0.8~0.9及び0.9~1.0のスパン対長さの比率を有するグループが前記周囲の長さを構成するそれぞれの割合を決定する。
【請求項12】
請求項1に記載の方法であって、ステップ(E)が以下を含む、方法:
ステップ(D)で決定されたそれぞれのパーセンテージ又はそれに基づく形態学的特徴付けのいずれかを表示する。
【請求項13】
請求項1に記載の方法であって、ステップ(E)が以下を含む、方法:
ステップ(D)で決定されたそれぞれのパーセンテージ又はそれに基づく形態学的特徴付けのいずれかに基づいて、前記形状の表示の再シェーディングすること、カラー化すること及び/又は強化することのうちのいずれか。
【請求項14】
請求項1に記載の方法であって、ステップ(D)で決定されたそれぞれのパーセンテージ又はそれに基づく形態学的特徴付けのいずれかに基づいて、前記形状が医療用画像内の形状の同心円状のセットの外側の境界であるか否かを決定することを含む、方法。
【請求項15】
請求項14に記載の方法であって、ステップ(D)で決定されたそれぞれのパーセンテージ又はそれに基づく形態学的特徴付けのいずれかに基づいて、前記同心円状の形状のセット及びそれによって撮像された組織の特徴を決定することを含む、方法。
【請求項16】
請求項1に記載の方法であって、ステップ(E)が以下を含む、方法:
前記形状の正規化画素密度、一連の同心円形状の相対的な中心化距離パーセント、一連の同心円形状のバランスの度合い、及び、一連の同心円形状の多形性の度合いのうちの1つ以上と組み合わせたそれぞれのパーセントの関数として、前記医療用画像に撮像された組織の形態を特定する。
ラジオミクス - 正規化画素密度(「NPD」)。
【請求項17】
以下を含む方法:
A.医療用画像の関心領域の画素強度を正規化する、
B.全体ではないにしても、少なくとも部分的に前記関心領域内に入る形状内の画素の平均強度を決定する、
C.ステップ(B)で決定された平均が、ステップ(A)で決定された画素の正規化された強度に対するパーセンタイルランクを決定する、
D.前記パーセンタイルランクの関数として、前記医療用画像を強調させるか、又は前記医療用画像に撮像された組織の形態を特定する。
【請求項18】
請求項17に記載の方法であって、ステップ(A)が以下を含む、方法:
i.前記関心領域内の画素の強度を調査し、強度の最小値と最大値とを特定する、
ii.これらの最小値と最大値を、適用可能な正規化ターゲットまで拡張するスケーリングファクタとオフセットとを決定する、
iii.前記関心領域内の前記画素の強度の値に、そのファクタとオフセットとを適用する。
【請求項19】
請求項17に記載の方法であって、ステップ(B)が以下を含む、方法:
正規化に続いて、前記形状内の画素の強度を合計し、そして、その合計をそれらの画素のカウントで割る。
【請求項20】
請求項17に記載の方法であって、ステップ(C)が以下を含む、方法:
前記関心領域内の画素の正規化された強度を調査し、そして、ステップ(B)で決定された前記平均強度を超える、又は、下回るのうちいずれかである強度を有するものをカウントする。
【請求項21】
請求項17に記載の方法であって、ステップ(D)が以下を含む、方法:
前記パーセンタイル・ランキングを表示する。
【請求項22】
請求項17に記載の方法であって、ステップ(D)が以下を含む、方法:
前記パーセンタイル・ランキングに基づく前記形状の再シェーディング、カラー化、及び/又はその他の表示強化のいずれか。
【請求項23】
請求項17に記載の方法であって、前記パーセンタイル・ランキングに基づいて、前記形状が前記医療用画像内の形状の同心円セットの外側の境界であるか否かを決定することを含む、方法。
【請求項24】
請求項23に記載の方法であって、前記パーセンタイル・ランキングに基づいて、形状の同心円セットの特徴、及び、それによって撮像された組織の特徴を決定することを含む、方法。
【請求項25】
請求項17に記載の方法であって、ステップ(D)が以下を含む、方法:
前記パーセンタイルランクの関数として前記医療用画像に撮像された組織の形態を特定する。
【請求項26】
請求項25に記載の方法であって、ステップ(D)が以下を含む、方法:
前記形状のスピキュレーション特徴付け、前記形状が一部を形成する一連の同心円形状の相対的な中心化距離パーセント、前記一連の同心円形状のバランスの度合い、及び、前記一連の同心円形状の多形性の度合いのうちの1つ以上と組み合わせた、前記パーセンタイルランクの関数として、前記医療用画像に撮像された前記組織の形態を特定することを含む。
ラジオミクス - 相対的な中心化距離パーセント(Relative Centralized Distance Percent RCDP)
【請求項27】
以下を含む方法:
A.医療用画像から一連の同心円形状の腫瘤の中心位置を見つける、
B.前記一連の同心円形状の最長径と最短径を決定する、
C.前記一連の同心円形状の中で、最も強い形状を特定する、
D.ステップ(C)で特定した前記形状の腫瘤の中心位置を求める、
E.ステップ(A)と(D)で求めた腫瘤の中心間の距離の関数として、及び、ステップ(B)で求めた前記最大径と前記最小径の関数として、相対的な中心化距離パーセントを決定する、
F.前記相対的な中心化距離パーセントの関数として、前記医療用画像を強調すること、又は、前記医療用画像に撮像された組織の形態を特定することのいずれか。
【請求項28】
請求項27記載の方法であって、ステップ(E)が以下を含む、方法:
以下の数学的関係式に従って前記相対的な中心化距離パーセントを決定する:
RCDP=DP/(OMSLD+OMSSD)
ここで、
RCDPは相対的な中心化距離パーセントであり、
DP=OMCP-DPCPであり、
OMCPは一連の同心円形状の腫瘤の中心であり、
DPCPは、ステップ(C)で特定された形状の腫瘤の中心であり、
OMSLDは、一連の同心円形状の中で最大径であり、
OMSSDは、一連の同心円形状の中で最小径である。
【請求項29】
請求項27に記載の方法であって、ステップ(B)が以下を含む、方法:
前記一連の同心円形状に収まる(fits)最小の円を求める。
【請求項30】
請求項27に記載の方法であって、ステップ(B)が以下を含む、方法:
前記一連の同心円形状の境界をなす(bounds)最大の円を求める。
【請求項31】
請求項27に記載の方法であって、ステップ(F)が以下を含む、方法:
前記相対的な中心化距離パーセントを表示する。
【請求項32】
請求項27に記載の方法であって、ステップ(F)が以下を含む、方法:
前記相対的な中心化距離パーセントに基づく、形状の再シェーディング、カラー化、及び/又はその他の表示強化のいずれか。
【請求項33】
請求項27に記載の方法であって、前記相対的な中心化距離パーセントに基づいて、前記形状が前記医療用画像内の形状の同心円セットの外側の境界であるか否かを決定することを含む、方法。
【請求項34】
請求項33に記載の方法であって、前記相対的な中心化距離パーセントに基づいて、前記形状の同心円セット及びそれによって撮像された組織の特徴を決定することを含む、方法。
【請求項35】
請求項27に記載の方法であって、ステップ(F)が以下を含む、方法:
前記相対的な中心化距離パーセントの関数として医療用画像に撮像された組織の形態を特定する。
【請求項36】
請求項35に記載の方法であって、ステップ(F)が以下を含む、方法:
一連の同心円形状のスピキュレーションの特徴、前記医療用画像の領域内の画素の正規化された強度に対するその一連の形状内の形状内の画素の平均強度のパーセンタイル・ランキング、前記一連の同心円形状のバランスの度合い、及び、前記一連の同心円形状の多形性の度合いのうちの1つ以上と組み合わせた前記相対的な中心化距離パーセントの関数として、前記医療用画像内に撮像された組織の形態を識別する。
ラジオミクス-バランス決定
【請求項37】
以下を含む方法:
A.医療用画像内で特定された一連の1つ以上の同心円形状のバウンディングボックスを決定する、
B.前記バウンディングボックスを複数の等しいサイズの領域に分割する、
C.1つ以上の閾値強度の上回る、下回る、又は範囲内であるのうちいずれか該当する、画素の各領域内のカウントを決定する、
D.各領域について決定された画素のカウントを、(i)対称線としてのX軸、(ii)対称線としてのY軸、及び(iii)対称線としてのX軸とY軸とを含む対角線のうちの1つ以上にわたって、他の各領域の画素のカウントと比較する、
E.ステップ(D)における比較の結果を合計することにより、一連の同心円形状のバランスの度合いを決定する、
F.前記バランスの度合いの関数として、前記医療用画像を強調すること、又は、前記医療用画像に撮像された組織の形態を識別することのいずれかを行う。
【請求項38】
請求項37に記載の方法であって、ステップ(D)が以下を含む、方法:
比較された各領域内の1つ以上の閾値強度を上回る/下回る/範囲内にある画素数の差を決定する。
【請求項39】
請求項38に記載の方法であって、ステップ(D)が以下を含む、方法:
比較された各領域内の1つ以上の閾値強度を上回る/下回る/範囲内にある画素数の差の絶対値をとる。
【請求項40】
請求項37に記載の方法であって、ステップ(F)が以下を含む、方法:
前記バランスの度合いを表示する。
【請求項41】
請求項37に記載の方法であって、ステップ(F)が以下を含む、方法:
前記バランスの度合いに基づく、前記形状の再シェーディング、カラー化、及び/又はその他の表示強化のいずれか。
【請求項42】
請求項37に記載の方法であって、以下を含む、方法:
前記バランスの度合いに基づいて、前記形状が前記医療用画像内の同心円形状のセットの外側の境界であるか否かを判定する。
【請求項43】
請求項42に記載の方法であって、以下を含む、方法:
前記バランスの度合いに基づいて、前記同心円形状のセット、及び、それによって撮像された組織の特徴を決定する。
【請求項44】
請求項37記載の方法であって、ステップ(F)が以下を含む、方法:
前記バランスの度合いの関数として、前記医療用画像に撮像された組織の形態を、特定する。
【請求項45】
請求項44に記載の方法であって、ステップ(F)が以下を含む、方法:
一連の同心円形状のスピキュレーションの特徴、前記医療用画像の領域内の画素の正規化強度に対するその一連の形状内の画素の平均強度のパーセンタイル・ランキング、一連の同心円形状の相対的な中心化距離パーセント、及び一連の同心円形状の多形性の度合いのうちの1つ以上と組み合わせたバランスの度合いの関数として、前記医療用画像内に撮像された組織の形態を特定する。
ラジオミクス-多形性判定
【請求項46】
以下を含む方法:
A.医療用画像内で特定された一連の同心円形状のカウントを決定する、
B.ステップ(A)で決定された前記カウントの関数として、前記医療用画像を強調すること、又は前記医療用画像に撮像された組織の形態を特定することのいずれかを行う。
【請求項47】
請求項46に記載の方法であって、ステップ(D)が以下を含む、方法:
ステップ(A)で決定された前記カウントを表示する。
【請求項48】
請求項46に記載の方法であって、ステップ(D)が以下を含む、方法:
ステップ(A)で決定された前記カウントに基づく、前記形状の再シェーディング、カラー化、及び/又はその他の表示強化のいずれか。
【請求項49】
請求項46に記載の方法であって、以下を含む、方法:
ステップ(A)で決定された前記カウントに基づいて、前記形状が前記医療用画像内の形状の同心円セットの外側の境界であるか否かを決定する。
【請求項50】
請求項49に記載の方法であって、以下を含む、方法:
ステップ(A)で決定された前記カウントに基づいて、形状の同心円セット、及び、それによって撮像された組織の特徴を決定する。
【請求項51】
請求項46に記載の方法であって、ステップ(B)が以下を含む、方法:ステップ(A)で決定された前記カウントの関数として、前記医療用画像に撮像された組織の形態を特定する。
【請求項52】
請求項51に記載の方法であって、ステップ(B)が以下を含む、方法:
一連の同心円状の形状のスピキュレーションの特徴、前記医療用画像の領域内の画素の正規化強度に対するその一連の形状内の画素の平均強度のパーセンタイル・ランキング、一連の同心円形状の相対的な中心化距離パーセント、及び一連の同心円形状のバランスの度合いのうちの1つ以上との組み合わせた、ステップ(A)で決定されたカウントの関数として、前記医療用画像内に撮像された組織の形態を特定する。
【発明の詳細な説明】
【技術分野】
【0001】
関連出願への参照
【0002】
本出願は、2021年8月12日に出願された米国特許出願番号17/400,616及び2021年8月10日に出願された米国仮特許出願番号63/231,697の優先権を主張するものであり、いずれもタイトルが“Radiomic Systems and Methods.”である。前述の米国特許出願番号17/400,616は、“Digital Image Analysis And Display System Using Radiographic Attenuation Data ”といタイトルである、2020年6月2日出願の米国特許出願番号16/890,496の一部継続出願である。そして、当該一部継続出願は、“Digital Image Analysis And Display System Using Radiographic Attenuation Data”というタイトルである、2019年5月31日出願の米国特許出願番号16/428,125の継続出願である。当該継続出願は、“Radiologic Image Viewer ”というタイトルである、2018年5月31日出願の米国仮特許出願第62/678,644号の優先権の利益を主張する。前述の出願及び特許のすべての教示は、参照により本明細書に組み込まれる。
【0003】
本特許文書の開示の一部には、著作権保護の対象となる資料が含まれている。著作権者は、特許商標庁の特許ファイル又は記録に記載されているように、本特許文書又は本特許開示のいずれについてのファクシミリ複製に対して何ら異議を唱えないが、それ以外のすべての著作権を留保する。
【背景技術】
【0004】
発明の背景
【0005】
人体の一部(手)のX線画像が初めて撮影されたのは1895年のことで、放射線学という学問分野が始まった。その数年後には、初めての医療診断への応用の一つとして示されたこととして、子供の喉につまった1セント硬貨を撮影した。しかし、X線を用いて、軟組織の特徴を識別することは、更に困難であることが示され、その理由として、X線の減衰(密度に依存して組織を通過する相対量)は非常にかすかなものであり、「X線」の最中に、且つ、結果的になる黒色の中で区別するのは困難だったからである。最初のマンモグラフィ装置が乳房組織の腫瘤を検出するために商業的に使用されるまで、何年もかかった。これらのマンモグラフィはX線フィルムを使用していた。デジタル・マンモグラフィは1972年に導入され、1990年代にはデジタル・マンモグラフィは標準的な医療行為となった(アナログイメージングからの移行の際に一部の科学者からの信用を失うという、隠れた詳細に関するいくつかの詳細に関する不安にもかかわらず)。
【発明の概要】
【発明が解決しようとする課題】
【0006】
現在、米国では毎年4,000万件のデジタル・マンモグラムが撮影され、その50%超がトモシンセシスと呼ばれる高度な3Dデジタル・マンモグラフィを使用している。デジタル・マンモグラフィは癌の早期発見が可能であることが証明されており、米国食品医薬品局によって承認された唯一のスクリーニング方法である。しかし、マンモグラフィは、追加撮影や不当な生検につながる早期検出と偽陽性とが多すぎるという、根強い欠点があるため、ますます精密な調査が増えることとなる。この2つの問題は、女性にとって有害となる健康への影響をもたらし、医療提供者にとっては運営コストや訴訟コストを増加させる。このような傾向を踏まえて、現在行われているいくつかの研究では、すべての女性に推奨されるスクリーニングレジメンの妥当性が再検討されている。
【0007】
大多数の患者にとって、マンモグラフィはうまく機能するが、女性の40パーセントは、白黒マンモグラフィにおいて、がんを「マスクする」可能性のある濃密な乳房組織を持っている。これは、事実であり、その理由として、腫瘍と自然に発生する濃密な乳房組織の両方が白黒マンモグラフィでは白く写るためである。自然発生的な濃密組織は腫瘍の形態学的特徴を不明瞭にし、放射線技師が、一般的に最も濃密である腫瘤の中心部から、一般的にあまり濃密でない腫瘍の辺縁部へと伸びるグレースケールのグラデーションを見ることをより困難にする。また、悪性腫瘍の顕著な特徴である、積極的な増殖を示す伸長した触手やspiculationと呼ばれるトゲや点を見ることも難しくなる。重要なことは、乳房組織が密な女性は、がんの自然発生率も高いということであり、従って、より優れたスクリーニング方法に関するニーズは、こうした女性の方が更に大きい。
【0008】
マンモグラフィは放射線画像診断の重要な応用であるが、先行技術の欠点に悩まされる医療用画像診断の応用は他にも数多くある。
【0009】
本発明の目的は、医療用、より詳細にはデジタル画像診断用の改良されたシステム、装置及び方法を提供することである。
【0010】
本発明の他の目的は、医療診断及び/又は治療に適したこのような改良されたシステム、装置及び方法を提供することである。
【0011】
本発明のさらに関連するこのような目的は、前述に関する従来技術の欠点を克服する、医療診断及び/又は治療のためのこのような改良されたシステム、装置及び方法を提供することである。
【課題を解決するための手段】
【0012】
発明の概要
【0013】
本発明は、例えば、グレースケールのデジタルフォーマットに変換された減衰データによって特徴付けられる、X線及び他の撮像モダリティから生成された画像の要素の強調表示を提供するデジタル画像処理のためのシステム、装置及び方法を提供する。
本発明は、
デジタル画像をレンダリングするために使用される減衰値をキャプチャし、そのデータを使用して、グレースケールの明瞭なグラデーションを識別し、例えば、人間の視覚のスペクトル内及びそれを超えるグレースケール・データを組み込み、
次に、グラデーションの範囲に基づいて境界を再帰的に画定し、画定された内部輪郭と外側の境界を有する不規則な多層視覚オブジェクトを形成し、そして、
画定された各層を強調し、及び、強調表示を元の画像の対応する領域上に重ね合わせ、
それによって、人間の視覚から以前は不明瞭であった、隠されていた、又は「マスクされた」腫瘤の潜在的な形態を明らかにする。
本発明は、減衰値(すなわちX線及び音波)によって生成されるすべてのデジタル画像に対して作動する。現在、本発明は、マンモグラムのような医療用X線画像中の臓器腫瘤を表示し、診断解釈を補助するために使用されている。
【0014】
他の態様において、本発明は、例えば、上述のシステム、装置及び方法を提供し、これらは、
医療用画像内の形状の周囲を歩いて(walking)、その周囲を定義する座標のリストを生成するステップと、
リストを、周囲上の変曲点によって分割された座標のグループに分割するステップと、 座標の各グループについて、スパン対長さの比率を決定するステップであって、ここで、「スパン」は、それぞれのグループの端点間のデカルト座標系上の距離を意味し、「長さ」は、それぞれのグループによって定義された経路に沿って移動して測定された距離の合計を意味する、ステップと、
選択されたスパン対長さの比率を有するグループが周囲の長さを構成するそれぞれのパーセンテージを決定するステップと、
それらのそれぞれのパーセンテージの関数として、医療用画像を強調させるか、又は医療用画像に撮像された組織の形態を特定することのうちいずれかを行うステップと、
を含む。
【0015】
本発明のさらなる他の態様は、例えば上述したようなシステム、装置及び方法を提供し、これらは、
医療用画像の関心領域内の画素強度を正規化することと、
関心領域内に全体ではないにしても少なくとも部分的に含まれる形状内の画素の平均強度を決定することと、
平均が画素の正規化された強度に対して相対的であるパーセンタイル・ランキングを決定することと、
パーセンタイル・ランキングの関数として医療用画像を強調すること又は医療用画像内に撮像された組織の形態を特定することのいずれかと、
を含む。
【0016】
本発明のさらに他の態様は、例えば、上述したようなシステム、装置及び方法を提供すし、これらは、
医療用画像内で特定された一連の同心円形状の腫瘤の中心の位置を求めること、
一連の同心円形状の最長径及び最短径を決定すること、
一連の同心円形状内で最も強い形状を特定すること、
形状の腫瘤の中心の位置を求めること、
腫瘤の中心間の距離の関数として、及び、最大径と最小径の関数として、相対的中心化距離パーセントを決定すること、
相対的中心化距離パーセントの関数として、医療用画像を強調すること、又は医療用画像に撮像された組織の形態を特定することのうちいずれかを行うこと、
を含む。
【0017】
本発明のさらに他の態様は、例えば、上述したようなシステム、装置及び方法を提供し、これらは、
医療用画像内で特定された一連の1つ以上の同心円形状のバウンディングボックスを決定するステップと、
バウンディングボックスを複数の等しい大きさの領域に分割するステップと、
各領域内で、1つ以上の閾値強度を超える、未満である、又は1つ以上の閾値強度内であるのうちのいずれかである画素のカウントを決定するステップと、
i)対称線としてのX軸、(ii)対称線としてのY軸、及び(iii)対称線としてのX軸とY軸を組み合わせた対角線のうちの1つ又は複数を横切って、各領域について決定された画素のカウントを他の各領域の画素のカウントと比較するステップと、
比較の結果を合計することにより、一連の同心円形状のバランスの度合いを決定するステップと、
バランスの度合いの関数として、医療用画像を強調させるか、又は医療用画像に撮像された組織の形態を特定することのうちいずれかを実行するステップ
ことを含む。
【0018】
本発明の他の態様は、例えば上述したようなシステム、装置及び方法を提供し、これらは、
医療用画像において特定された一連の同心円形状における形状のカウントを決定することと、
そのカウントの関数として医療用画像を強調すること又は医療用画像に撮像された組織の形態を特定することのいずれかを行うことと、
を含む。
【0019】
本発明の前記及びその他の態様は、図面及び以下の説明で明らかである。
【0020】
特許又は出願ファイルには,少なくとも1つのカラー図面が含まれている。カラー図面を有するこの特許又は特許出願公開公報の写しは、請求及び必要な手数料の支払に基づき、国内官庁から提供されるであろう。
【0021】
図示された実施形態のより完全な理解は、図面を参照することによって達成され得る:
【図面の簡単な説明】
【0022】
【
図1】
図1は、本発明の一実施態様によるシステム10と、本発明が実施されうる環境を示している;
【
図2】
図2は、画像解析のための本発明によるプロセスを概観するフローチャートである;
【
図3】
図3は、本発明によるシステムにおける減衰値の捕捉を示すフローチャートである;
【
図4】
図4は、本発明によるシステムにおける主要なグレースケール範囲のシーケンシャルグループ化の特定を示すフローチャートである;
【
図5】
図5は、本発明によるシステムにおけるポリゴンの作成と並べ替え、及び組織密度勾配の輪郭作成を示すフローチャートである;
【
図6】
図6は、本発明によるシステムにおける、組織形態を反映する空間的に関連したポリゴンの組み立てを示すフローチャートである;
【
図7】
図7は、本発明によるシステムにおける、組み立てられたポリゴンのレーティング、測定、強調、及び、表示を示すフローチャートである;
【
図8】
図8は、本発明によるシステムにおいて形態学的に関連するものとして保存されたポリゴンに対する検索可能な基準の作成を示すフローチャートである;
【
図9】
図9は、本発明による画像強調のためのポップアップユーティリティウィンドウがない場合とある場合の放射線スキャンを示す;
【
図10】
図10は、本発明によるシステムにおいて、グロースリング(Growth Rings、GR)と呼ばれる輪郭のある形状を明らかにする、単一のグレースケール値での連続したグループ化を示している;
【
図11】
図11は、概念的なPGM(Pixel Gradation Mass)と、収束する外向きの成長点を持つマンモグラムに表示されたPGMを示している;
【
図12】
図12は、本発明によるシステムにおけるマンモグラム上の腫瘤に見られるグロースリングを表す同心円状のリングの図解である;
【
図13】
図13は、本発明による画像強調のためのポップアップユーティリティがない場合とない場合のマンモグラフィを示す;
【
図14】
図14は、本発明によるシステムにおいて、ある数のグロースリングが識別され、描画されることにより、PGMの輪郭とサイズが定義されることを示している;
【
図15】
図15は、本発明によるシステムにおいて、GRが外側に伸びるにつれて増加する平均面積を計算することにより、腫瘤の密度が決定されることを示す;
【
図16】
図16は、本発明によるシステムにおいて、PGMの白色度が中央GRの輝度によって決定されることを示す;
【
図17】
図17は、本発明によるシステムにおけるポップアップ・ユーティリティ・ウィンドウの設定の変更を示す図である;
【
図18】
図18は、本発明によるグロースリングのピキュレーションの定量化と特性評価の方法を示している;
【
図19】
図19は、本発明による正規化画素密度決定方法を示す;
【
図20】
図20は、本発明による相対中心化距離パーセント決定方法を示す;
【
図23】
図23は、本発明による多形性決定の方法を示している。
【発明を実施するための形態】
【0023】
図解の実施形態の詳細な説明
【0024】
【0025】
図1は、本発明の一実施態様によるシステム10と、本発明が実施され得る環境を示している。図示のシステム10は、ネットワーク20を介して1つ以上のクライアント・デジタル・データ・デバイス14~18に結合されるサーバ・デジタル・データ・デバイス12を含む。
【0026】
サーバデジタルデータデバイス12は、メインフレーム、ミニコンピュータ、ワークステーション、又は、以下の議論及び本明細書の他の箇所でデバイス12に帰属する機能を実行するために本明細書の教示に従って適合されるような、当技術分野で公知のタイプの他のデジタルデータデバイスを含む。サーバ12は、スタンドアロン装置を含んでもよいし、又は、ここに示すタイプの他の装置若しくはそれ以外と共同収容されてもよい。
【0027】
クライアントデジタルデータデバイス14~18は、ワークステーション、デスクトップコンピュータ、ラップトップコンピュータ、ポータブルコンピューティングデバイス、スマートフォン、又は以下に続く議論及び本明細書の他の箇所でそれらのデバイス14~18に帰属する機能を実行するために本明細書の教示に従って適合される、当技術分野で公知のタイプの他のデジタルデバイスを含む。1つ又は複数のクライアント14~18は、スタンドアロン装置を含んでもよいし、又は、ここに示すタイプの他の装置若しくはそれ以外と共同収容されてもよい。非限定的な例として、いくつかの実施形態では、1つ又は複数のクライアント14~18は、非限定的な例としての、CTスキャナ、トモシンセシス装置などの医療用撮像装置を含むか、又はそれと共同収容されることがあり、一方、同じ又は他の実施形態では、他のそのようなクライアントは、パーソナルデジタルアシスタント、スマートフォンなどを含むか、又はそれらで収容されることがある。
【0028】
クライアント装置14~18は、装置14~18によって分析された静止画像及び/又は動画、ならびに場合によってはサーバ12によって分析された静止画像及び/又は動画を表示及び/又はその他の方法で提示するために、グラフィカルディスプレイ14A~18A、又は、本明細書の教示に従って適合された、当技術分野で公知のタイプのその他の出力装置(クライアント14~18と一体化されているか、それらにネットワーク接続されているか、その他の方法であるかを問わない)にそれぞれ結合され得る。サーバ12は、望ましい場合又は必要な場合には、そのようなグラフィカルディスプレイ(図示せず)に同様に結合することができる。
【0029】
ネットワーク20は、ローカルエリアネットワーク、ワイドエリアネットワーク、メトロポリタンネットワーク、インターネット、及び/又は、図示された装置間の(リアルタイム又はその他の)情報の転送をサポートするために、本明細書の教示に従って適合された、当技術分野で公知のタイプの他のネットワーク若しくは通信媒体(無線、有線、又はその他の)若しくはそれらの組み合わせを含む。
【0030】
図1に図示され、上述された実施形態は、本発明がここに示された以外の実施形態でも実施され得ることを例示するものであることが理解されよう。したがって、非限定的な例として、図面には1つのサーバ及び3つのクライアント装置が示されているが、これは例示であり、他の実施形態では、より多い又はより少ない数のこれらのいずれかの装置を含むことができることが理解されよう。さらに、いくつかの実施形態では、本明細書においてサーバ12に割り当てられた操作は、個々に又は協調して動作するクライアント14~18のうちの1つ又は複数によって実行されてもよく、逆に、クライアント装置14~18に割り当てられた操作は、サーバ12によって実行されてもよいことが理解されよう。
【0031】
動作の概要
【0032】
以下に、本発明に従った画像解析のためのクライアント装置14~18の動作方法を説明する。そのような目的のためのそのような装置14~18のプログラミングは、以下の議論及び本明細書の他の箇所を考慮すれば、当業者の知識の範囲内である。以下の議論で明らかなように、それらの装置は、サーバ12の支援なしに独立して動作することができる。
【0033】
図2は、クライアント装置における画像解析及び/又は強調のための本発明の方法の概要である。図示の方法は、デジタル画像取得装置によって提供される指定領域内の減衰データをキャプチャする。(ステップ101)。図示された方法は、最初に、画像の領域内又はフルサイズのマンモグラムのような画像全体の指定された範囲内の主要なグレースケール値を特定することによって画像分析を実行する。(102)コンピュータの機能によって展開される反復プロセスを使用して、図示された方法は、主要なグレースケール範囲のグラデーション境界について指定された領域をスキャンし、それらの境界をトレースし、連続線を描く。最良の実施形態として、図示の方法は、同じデジタル画像又はデジタル画像の指定領域に適用される各グレースケール範囲(4、8、16、32、64、128、256)で同じ反復プロセスを使用する。この結果、最初は、様々なビットレベルで描画された数十万の個々の描画されたポリゴンが得られ、各ポリゴンは、主要なグレースケール範囲内で隣接する画素を連結することによって定義された。このことは、クロージャ機能のあるなしにかかわらず行われる。(103)図示の方法は、コンピュータの機能によって展開される反復プロセスを使用して、全てのポリゴンのインベントリを作成し、異なるビットレベルで形成された重複を排除する。同じ反復プロセスを用いて、図示の方法はポリゴンをソートし、互いに空間的関係を共有する個々のポリゴンを用いてマルチポリゴンオブジェクトを組み立てる。(104)図示された方法は、組み立てられたマルチポリゴンオブジェクトの特性及びサイズを測定し、画像取得装置によって割り当てられた元の減衰値から導出されたグレースケール範囲に対応する、構成ポリゴンの各々にエンハンスメント(強調)を適用し、それによって、組織密度に対応するグレースケール勾配をハイライトするためにエンハンスメントを使用する。(105)図示された方法は、強調されたマルチポリゴンオブジェクトを組織腫瘤のデジタル表現として表示し、その腫瘤のポリゴン層の数(AQ-attenuation quotient)のメトリクス、並びにその推定直径、面積及び体積を提供する。(106)マルチポリゴンの“腫瘤”は、視覚的解析を強化するために周囲の背景とともに、又は背景なしで表示することができ、他のマルチポリゴンオブジェクトが保存されている形態学的データベースに保存することができ、他のマルチポリゴン組織腫瘤との検索や比較を可能にする。
【0034】
減衰値を捉える
【0035】
図3を参照すると、本発明によるシステム及び方法(以下、文脈から別段明らかでない限り、総称して「システム」又は「方法」)は、2D及び3Dの両方において、放射線画像収集装置すなわちマンモグラフィX線装置によって記録された減衰データに基づいてデジタルグレイスケール値を捕捉する。データは、現在1024段階のグレースケールまで対応可能なデジタル形式で表示される。システムは、グレースケール値を256へと変換し、これが、デジタルマンモグラフィ画像の処理に最も良好なモードとしてみなされている;しかし、このシステムでは、グレースケールの範囲4で使用し、現在定義されている1024グレースケールの上限まで処理することができる。マンモグラフィの目的のために、撮影画像はDICOMフォーマット要件に適合するように処理されている。しかし、このシステムは、あらゆるデジタル画像フォーマット、すなわち、jpeg、gif、png、bmp及びその他のデジタル化されたフォーマットを変換することができる。
【0036】
主要なグレースケール・レンジ・シーケンシャル・グルーピング(GRSG)を特定する。
【0037】
図4を参照すると、本発明によるシステムは、フルスケールのマンモグラムのような解析のために指定された場合、画像の指定された領域又は画像全体のグレイスケールスペクトルをスキャンする。画素ごとの分析を使用して、システムは、指定された領域で使用されている、最も一般的(common)な連続する上位4つのグレースケール・レンジ・シーケンシャル・グルーピング(GRSG)を決定する。(102:1)この反復プロセスは、上位3つの一般的なGRSGを決定するために使用することもできるし、4つを超えるGRSGを識別するために使用することもできる。デジタル・マンモグラフィの好ましい使用態様は、4つのGRSGを使用し、4から256までの各グレイスケール範囲において指定領域の画像分析を行うことである。より大きなグレースケール(512以上)での画像解析のためには、より大きな粒状性を反映して、より多数のGRSGが識別され得る。
【0038】
組織密度勾配の輪郭を描くポリゴンを作成し、ソートする
【0039】
図5を参照すると、コンピュータの機能によって展開される反復プロセスを使用して、本発明によるシステムは、4つのGRSGを使用して、指定された領域内のグレースケールの勾配エッジを定義してトレースし、ポリゴンの形状の輪郭を描く連続線を形成する。これは、コンピュータの反復機能を使用して、外側のx/y経路を定義するようにGRSGの値範囲に従うことによって、出現するポリゴンの経路に隣接する画素を連結することによって行われる。オプションとして、上記で定義したGRSG法の代わりにエッジ検出を使用してポリゴンをポリゴンすることもできる。
【0040】
このシステムでは、クロージャを使用せずにポリゴンを作成し、その結果を保存する。次に、システムは、得られたポリゴンの外側の境界にクロージャを適用する(それをトレースして潜在的なx/y経路の異常を修正し、それによって、幅又は高さのいずれか一方が0.09パーセントより小さい画素ランのギャップを閉じることによって)。もしも、このことで画素の値が20未満になった場合には、20を超える画素を使用する。ここで言及した本発明システムのプロセスは、マンモグラフィの現在の最良モードを表している。クロージャを実行する際に、他のカットオフ値を使用してもよい。
【0041】
本発明による方法は反復プロセスを使用し、各グレイスケールレベルに対してGRSGを定義し、次にそれらのレベル--4,8,16,32,64,128,256でポリゴンをトレースする。この方法では、上記のようにクロージャを使用し、その結果を保存し、数十万の個々のポリゴンを作成する。
【0042】
コンピュータを用いた反復処理を用いて、最初に作成された多数のポリゴンをソートし、以下のものを除去する:1)異なるグレイスケールレベルとクロージャによって生成された重複、2)対象とする組織塊を表すことができない異常なポリゴン形態(即ち、乳房インプラント、移植された装置、マンモグラムのエッジのような物理的バリア、又はマンモグラムにおける圧縮の既知のアーチファクトなど)を定義する比率によって設定された許容パラメータを超える形状を仮定するポリゴン。この方法では、元のグレースケール値の平均によってポリゴンを順次ソートし、グレースケール値が同じ場合は、最も小さいものから順にサイズ順に並べる。
【0043】
空間的に関連したポリゴンを組み立てる;組織の形態を反映させる
【0044】
図6を参照すると、本発明によるシステムは、コンピュータ、例えば14~18によって展開される反復プロセスを使用して、ポリゴンを、指定された領域、すなわち視覚化ウィンドウによって定義された領域、又は、マンモグラム全体に含まれる腫瘤の組織形態を反映するマルチポリゴンオブジェクトに組み立てる。コンピュータの反復機能を使用して、システムは、同じx/y領域に重なる互いに包含するポリゴンを組み立てる(「スタック」する)。このシステムは、密度勾配に対応する階層に基づいてポリゴンの積み重ねを順序付ける「子-親」の関係に基づいて順序付けを行う。最も高い密度を登録するポリゴンは腫瘤の中心に位置する。これは、悪性腫瘤は一般的に密な中心を持ち、悪性組織は密度が低くなるにつれてその中心から放射状に広がるという事実を反映している。このシステムは、低密度のポリゴンの境界の中に、より高密度のポリゴンがフィットするように、高密度から低密度へ、最小から最大へとこれらのポリゴンを組み立てるために、コンピュータによって展開される反復プロセスを使用する。その結果、低密度のポリゴンの境界の中に、より高密度のポリゴンがいくつも存在することになり、組織形態の複雑さを反映することになる。
【0045】
組み立てたポリゴンのレーティング、測定、強調、表示
【0046】
図7を参照すると、コンピュータ、例えば14~18を用いた反復プロセスを用いて、本発明によるシステムは、完成した「腫瘤」を構成するポリゴンの総数を記録し、それを「減衰係数」(AQ)と呼ばれるレーティング値として提示する。多変形ポリゴン(密度の低いポリゴンの中に密度の高いポリゴンがある)の場合、表示されるAQは最も密度の高いポリゴンのスタックのものである。
【0047】
このシステムでは、コンピュータを使用して、画素カウントを用いて最大径、平均径、最小径を測定し、これらの測定値をDICOMファイル又は他の標準化データで定義された画像取得ミリメートル/センチメートルに変換する。同様の画素カウント処理を用いて、本発明は、腫瘤の最大ポリゴンの面積を計算する。三次元画像の場合、連続するトモシンセシスのスライスで見た腫瘤の面積は、体積を計算するために、スライス間の既知の距離を考慮してコンピュータによって要素化(factor)される。
【0048】
システムは、グレースケール範囲及び/又は人間の目が区別できる色を使用して、各ポリゴンを再シェーディング又はカラー化する(使用するディスプレイモニターの容量に応じて)。マルチポリゴンの「腫瘤」は、視覚分析を強化するために、周囲の背景と一緒に表示することも、背景なしで表示することもできる。
【0049】
形態関連として保存されたポリゴンに対して検索可能な基準を作成する。
【0050】
図8を参照すると、2次元及び3次元の腫瘤を検索する基準は、対象となる腫瘤のすべての構成ポリゴンの比較に基づいている。この比較は、相対的な大きさが異なっていても、類似した形態の腫瘤を比較できるようにするために、一組のパーセンテージを通して行われる。これらのパーセンテージに基づく基準を作るために、本発明はコンピュータを使用して、各腫瘤(組み立てられたポリゴン(複数可))の周囲に可能な限り狭い正方形を定義し、その正方形の面積を使用して相対的な比較パーセンテージを計算する。以下に基づく比較パーセンテージが計算される。
【0051】
1)1~200%の範囲で表される各腫瘤の高さと幅の比。
【0052】
2)正方形全体に占める、ポリゴンが使用する画素のパーセンテージ。
【0053】
3)各正方形内のx、y画素の平均位置-相対的な位置関係を定義する。
【0054】
4)垂直方向及び水平方向のピクセルランレングスの平均、ここで、ランレングスとは、対角線上ではなく、水平又は垂直方向に連続し、整列した画素のセットとして定義される。
【0055】
上記の計算を実行するためにコンピュータを使用することで、相対的な大きさの違いや細かい形態的特徴のばらつきにもかかわらず、データベースに保持されている他の複数のポリゴンの組織腫瘤を検索し、比較することができる。
【0056】
利点
【0057】
先行技術の3Dマンモグラフィ撮像装置は、減衰の極めて僅かな差異-グレースケール撮像に変換されたときの区別-を補足するが、これは人間の視覚の範囲を超えるものである。 本発明によるシステムは、各画素に割り当てられる減衰値を捕捉することによってこの問題を克服し、それによって可視範囲と不可視範囲における様々な勾配を計算し、次にそれらの勾配を使用して、腫瘤の輪郭を反映するポリゴンをトレースする。このようなシステムは、次に、空間的に関連するポリゴンを形態学的な全体に再組み立てし、各グラデーションレイヤーをカラー化して構成グラデーションを区別することにより、一旦隠された形態学的な詳細を明らかにする。さらに、本発明によるシステムは、減衰値レベルで腫瘍の輪郭を分離することができるので、他の革新的な計算が可能である。例えば、システムは減衰値データを使用して、トモシンセシス撮像が合成「3D画像」をレンダリングするために使用する2Dスライスの各々における腫瘍のサイズ及び形状を計算することができる。その結果、本発明によるシステムは、乳癌の治療オプションを検討する際の重要なメトリクスであるマンモグラムにおける腫瘤の体積を計算することができる。
【0058】
先行技術では、コンピュータ支援画像ソリューションが、コンピュータ支援診断として知られるマンモグラフィに適用されてきた。このようなシステムは、一般に、ルールに基づくパターン認識を用いて、マンモグラム上で悪性腫瘤を含む可能性のある領域を特定していた。CADシステムは、マンモグラフィ上で疑わしいと思われる領域にX又はその他の図形で印をつける。しかし、2015年のメガスタディでは、CADは乳癌検出を改善しないと結論付けられ、今日、CADは診療報酬の対象外となり、放射線科医からほとんど見放されている。マンモグラフィにおけるコンピュータ支援検出への新たな希望は、様々な機械学習アプリケーションの出現によってもたらされた。CADと同様に、これらのシステムは疑わしい領域を特定しようとしている。さらに、これらの新しい機械学習/AIシステムは、疑わしい領域をマークするだけでなく、悪性腫瘍の可能性のレーティングとなるスコアを作成することを意図している。機械学習/AIアプリケーションは、白黒デジタル画像内のパターン解析と認識から生じる結果を出す。システムは既知の悪性腫瘤でソフトウェアを「訓練」し、進化するアルゴリズムを使って対象のマンモグラムに現れる類似の白黒パターンを照合する(パターンが類似すればするほど、悪性のスコアが高くなる)。ソフトウェアがより多くの画像で訓練するにつれて、そのパターン認識、及び、関連するスコアリングが向上することが期待される。
【0059】
本発明によるシステムは、先行技術のパターン認識システムとは異なる。本発明によるものは、既知の悪性腫瘤を有する一組のキュレーションされたマンモグラム上で訓練せず、領域を疑わしいものとしてマークせず、パターン認識に基づく予測定量化を提供する。本明細書で説明するように、本発明によるシステムは、デジタル画像取得装置によって取り込まれ、マンモグラムのようなデジタル画像に記録された減衰値の処理を通して、潜在的なとなる形態を明らかにする。さらに、本発明によるシステムは、各対象画像上で独自に計算された画素グラデーション輪郭によって定義されたカラー化を利用することにより、視覚化を通じて結果を表示する。メトリックス(明らかになった腫瘤の層数、直径、面積、体積)は、対象画像に具現化された密度勾配の輪郭から直接計算されるものであり、パターン認識や機械学習の学習済みデータセットの使用の結果ではない。
【実施例】
【0060】
以下に説明するのは、本発明による画像解析結果のポップアップ表示を提供する本発明による例示的なシステムにおけるクライアント装置14~18及びサーバ12の動作である。このような目的のためのこのような装置12~18のプログラミングは、以下の議論及び本明細書の他の箇所を考慮すれば、当業者の知識の範囲内である。
【0061】
1.本実施例では、本発明によるシステムにおいて、放射線画像をプープウィンドウ(以下「DeepLookウィンドウ」と呼ぶ)で表示するために使用されるユーティリティについて説明する。このポップアップユーティリティは、放射線画像を表示、評価及び/又は比較するために使用される医療用モニタのディスプレイ及び/又は他のデジタルディスプレイ上で直接動作する。これは、現在のモニタのPGM(Pixel Gradation Mass)画素設定のスクリーングラブを実行し、そして、それらを分析する。
図9の画像は、DeepLookウィンドウを使用した場合と使用しない場合のマンモグラフィを示す。
【0062】
2.ポップアップ・ウィンドウをサポート技術は、デジタル画面から直接画素グラデーションを解析する。画像取得に使用されたモダリティに関係なく、表示された画像を解析する。このソフトウェアは、マンモグラフィ又は超音波検査を含むがこれらに限らず、グレースケール又はカラーで表示されるあらゆる医療用画像で動作する。
【0063】
3.ソフトウェアは、グレースケールの連続体上で類似した明るさを持つとみなされる画素をグループ化する(カラー画素は対応するグレースケールに変換される)。DeepLookはそれらを単一のグレースケール値に変換し、連続した領域を作り出す。
図10に示すように、単一のグレースケール値で連続的にグループ化すると、グロース・リング(GR)と呼ばれる輪郭のある形状が現れる。
【0064】
4.グロースリング(GR)を作成するグループ化方法は、相対的な明るさに従って順序付けを確立する。放射線(X線)、MRI、MBI、その他の技術では、白から黒への降順で順序付けが行われ、超音波では黒から白への昇順で順序付けが行われる。この順序付け方法は、重複するGRを作成する。GRは再帰的であり、各GRのグループ化されたグレースケール値に従って、形状の中の形状として表示される。
【0065】
5.このグループ化、順序付け(降順又は昇順)、及び再帰的な重複は、1つ又は複数の点から画素グラデーションマス(PGM)と呼ばれる最終的な外向きの形状への外向きの成長を効果的に表示する。注:腫瘤は、外側に成長するにつれて収束するいくつかの成長点を持つ可能性がある。
【0066】
6.
図11において、左の画像は概念的なPGM(Pixel Gradation Mass)である。
図11の右側は、マンモグラムに表示されたPGMで、収束する外側への成長点がある。
【0067】
7.ポップアップ・ウィンドウをサポートする技術は、まず1画素・レベルでグレースケールを区別する、グラデーションは通常の人間の視覚の範囲を超える。そして、上記の項目#3と#4で説明した画素のシェーディンググループ化によって作成された構成要素であるグロース・リング(GR)をカラーでハイライトする。このGRは人間の目には見えないか、見えにくいものである。このソフトウェアは、画素グラデーションマス(PGM)内のGRをハイライトし、区別するためにカラー化を適用する。
【0068】
8.
図12は、マンモグラフィ上の腫瘤に見られるグロース・リングを同心円状に表した図である。
図12の左側には、ボックスのなかに、臓器の腫瘤のグロース・リングを表す同心円状の輪が含まれている。空間は、ブランクに近いように見えるが、そうではない。同心円状のリングは存在するが、各リング間のグレースケールの区別について、見た目で効果的に区別することは不可能である。
図4のボックスの右側にあるのは、ソフトウェア技術によって強調されたまったく同じ画像である。スケールカラーでハイライトすることによりリングを描いている。
【0069】
9.上の図解とは異なり、臓器組織の放射線画像から得られるグロース・リングは不規則な形をしており、きれいに描出されていない。以下では、この技術を2Dマンモグラムに直接適用している。
図13では、左側の画像はマンモグラム上の明るい白い領域である。これは一般的に腫瘤の可能性を示すが、均一な白さのため特徴を識別するのは難しい。
図13の右側は、ポップアップユーティリティで見た、同じ明るい白い領域である。ポップアップユーティリティの技術により、12個超のGR(Growth Rings)を持つPGM(Pixel Gradation Mass)が表示されるため、臓器の同心円状の画素シェーディングが見える。
【0070】
10.ポップアップユーティリティの背後にある技術と方法は、比率、加重平均技術、及び画素グラデーションマス(PGM)の寸法を確立するための他の計算のセットを使用する。PGMの輪郭と大きさは、画素グラデーション解析(上記項目#3-6)により作成されたグロース・リング(GR)の総数から生じ、グラデーションは画像取得モード(放射線、超音波など)に応じて昇順又は降順に行われる。特定され描出されたグロースリングの数がPGMの輪郭とサイズを規定する。
図14を参照。
【0071】
11.ポップアップユーティリティの背後にある技術と方法は、ユーザに情報を提供し、比較と分析を支援するために、0~10のスケールで表された全体的な密度値を提供する。画素・グラデーション・マス(PGM)の密度レーティングは、グロース・リングが中心から放射状に広がるにつれて増加する平均面積を計算することによって決定される。
【0072】
密度の定義:腫瘤の密度は、GRが外側に伸びるにつれて増加する平均面積を計算することによって決定される。密度のレーティングは、他のすべてのマッピングされた腫瘤に対して0から10までで正規化される。
図15の図の密度は7.5である。
【0073】
12.ポップアップユーティリティの背後にある技術と方法は、放射線画像における密度に対応する「白色度」(又は超音波や類似のモダリティの「暗さ」)の全体的な尺度を提供する。白さ(又は暗さ)の値は0~10のスケールで表され、ユーザに情報を提供し、比較や分析を支援する。PGM(Pixel Gradation Mass)の白色度は、PGM内のコア層の密度レーティングによって決定される。
【0074】
白色度の定義:PGMの白色度は、中央のグロースリング(GR)の明るさによって決定される。白色度は、ポップアップユーティリティのアウトラインで定義された領域内の他のすべてのマッピングされた腫瘤に対して0から10まで正規化される。ウィンドウのサイズを拡大又は縮小することが可能で、その結果、新しい比較計算が行われる。
図16の図は、0~256のグレースケールで白色度が10.0である。
【0075】
13.ポップアップユーティリティのデフォルト設定では、ポップアップ・ウィンドウの外周の範囲内で最も多くのグロースリング(GR)を持つ画素グラデーションマス(PGM)が表示される。デフォルト設定は、ウィンドウ内でハイライトされる腫瘤の数を拡大又は縮小するためにユーザが変更することができ、設定ウィンドウのドロップダウンメニューによって、腫瘤が表示されるために必要なGRの最小数を設定することができる。さらに、ウィンドウの表示は、以下の4つの相互に関連する変数のいずれかを調整することによって、手動でフィルタリングすることができる。これらの変数は、ウィンドウの上部にあるポップアップユーティリティメニューバーの設定アイコンをクリックすることで操作できる。
図17に示すように、以下の4つの変数がある:
【0076】
R=グロース・リング(GR)の数。
【0077】
L=同じポップアップ・ウィンドウで分析されている他の画素グラデーションマス(PGM)に対する一番外側のGRのサイズ。1=最小、N=最大-1~N。
【0078】
W=PGMの最高グレイスケール・グループ化されたGR値(X線用)、又は最低グレイスケール値(超音波用)。
【0079】
D=上記#11に記載されているPGM密度。
【0080】
14.ポップアップユーティリティの背後にある技術と方法は、各画素グラデーションマス(PGM)に関連する数値のユニークなセットを作成し、それらを総合して腫瘤の電子「プロファイル」を作成する。腫瘤組織プロファイル(MTP)と呼ばれるこの電子プロファイルは、カスタムMTPデータベースの特殊な視覚ベースの検索に使用することができ、追加の医療用画像から得られた他のMTPとの一致や相関を明らかにする。
【0081】
疑似 -コード
【0082】
以下は、PGM(Pixel Gradation Mass)及び上述した能力を作成するための擬似コードである:
【0083】
1.ポップアップ・ウィンドウを解析すべき画面領域上に移動する。あるいは、*.jpg、*.gif、DICOM、*.PNG、*.TIFFなどのデータファイルから、画像の特定の領域を解析することもできる。
【0084】
2.現在のモニタの画素の「スクリーングラブ」を行う。あるいは、*.jpg、*.gif、DICOM、*.PNG、*.TIFFなどの画像ファイルを、「スクリーングラブ」と同様の画素表示に変換して使用することもできる。
【0085】
3.ポップアップ・ウィンドウの表示の真下にある領域を場所指定する。あるいは、画素表示に変換された画像ファイルから領域を選択する。選択したファイル内のこれらの画素をスタンドアロンファイルにコピーする。あるいは、選択した領域のオフセットや、画素情報を読み取り管理する同様の方法を使用して、取り込んだ画素メモリから作業する。
【0086】
4.選択した領域で連続する画素グループを検索し、明るさでソートしたリストを作成する。以下は、DeepLookポップアップ・ウィンドウで使用される、連続画素・グループの作成するためのステップである。連続画素・グループとは、同じシェード、又は類似のシェードを持つ画素のグループで、接触している(「連続」している)画素のグループである。あるいは、連続画素・グループを生成する他の任意の方法を使用することもできる。
【0087】
「連続画素の生成」に使用されるDeepLook擬似コード:
【0088】
A.「スクリーンでグラブした」すべての画素について、各画素に1つのグレースケール値を持つ整数の配列を作る。グレースケールの最大値は可変である。DeepLookの実装では、グレースケールの最大値は255である。右上の画素から始めて、選択領域内で左から右へ、上から下へと作業し、各画素に割り当てられたグレースケール値を表す1つの整数値を作成する。赤=緑=青の場合、値は現在の赤の値となる。赤、緑、青がすべて同じでない場合は、画素の値をグレースケールに変換するために、カラー・トゥ・グレースケール・画素公式を使用する。この実装では、「luma=red*0.3+green*0.59+blue*0.11」を使用する。あるいは、グレースケール・画素表現でなくても、画素の3つのRGB値から1つの値を作成するために、任意の式やアルゴリズムを使用することもできる。
【0089】
B.グレースケール配列を、Xからグラブ幅、Yからグラブ高さ、つまりグラブ領域の矩形表現として使用する。画面領域に対して可能な最大数のグレーのシェードから始めて、連続する画素のグループに対して配列をスキャンする。配列をスキャンするごとに、配列の各値のグレースケール値を2のべき乗(ビットシフトを右に1)していき、最大値が3になるまで減らす。このことは、全部で、4つの可能なグレーのシェードとなる。
【0090】
配列の最初のスキャンでグレースケールの最大値が255だった場合、どの配列要素も持ちうる最大値は255となる。配列の2回目の走査では、最大値は127となり、3回目では63となる。
【0091】
各配列スキャンで、連続する画素グループが見つかったら、そのグループを定義するパラメータを保存しなければならない。この実装において後で使用する以下のパラメータを、この実装では保存しておく。あるいは、後日使用されるかもしれないし、又は、されないかもしれない任意の追加パラメータを保存することもできる。また、現在の実装に基づく以下のパラメータは、スキップすることができる。
【0092】
1.連続画素群を含み、そして、輪郭を描くX、Y画素点パス。
【0093】
2.すべての連続画素グループは、形状を囲む実際の画素矩形によって特定される。 形状がその画素矩形でカバーする画素面積のパーセンテージ。
【0094】
3.形状に使用される各画素の、実際の画素矩形に対する平均画素X位置。
【0095】
4.形状に使用される各画素の、実際の画素矩形に対する平均画素Y位置。
【0096】
5.形状を構成する右から左への連続した画素長の平均ランレングス。
【0097】
6.形状を構成する上から下への連続した画素長の平均ランレングス。
【0098】
7.形状の幅
【0099】
8.形状の高さ
【0100】
9.XY点パス(上記1)の総XY点数
【0101】
10.形状の平均グレースケール画素値。
【0102】
11.保存された各形状の各画素のXY位置。
【0103】
C.保存された形状のリストを巡回し、重複する形状を削除する。
【0104】
5.上記4(B)で保存した形状データを使って、見つかった形状のマトリックス表を作成する。この表は、形状が交差したり及び/又は重なったりする場所を特定し、同心円状の画素グラデーションを作成する際に使用する。
【0105】
6.同心円状の画素グラデーションの腫瘤を検索し、そのリストを作成する。同心円状の画素グラデーションを検索する手順は以下のステップに分解される(あるいは、同心円状の画素グラデーションを検索する他の代替方法を用いることもできる):
【0106】
A.形状のリストを、明るいものから順に並べ替える。
【0107】
B.リストの先頭から始めて、まだ腫瘤に割り当てられていないリスト上の各形状について、以下のステップB.1を実行する:
【0108】
B.1上記のステップ5で作成した形状のマトリックス表を使って、形状の画素行と列を検索し、その形状を完全に囲む形状を探す。現在の形状を完全に囲む形状が見つかり、以下のいずれかが真であれば、リストの次の形状をつかむ:
【0109】
1.その平均グレースケールが、現在の形状の平均グレースケールより大きい。
【0110】
2.見つかった形状のグレースケールから現在のグレースケールの形状を引いた絶対値が、Nより大きい。この実装においてはN=6である。あるいは、任意のN値を使用することもできる。
【0111】
3.見つかった形状の総面積がNより大きい。この実装では、Nは形状の大きさによって異なる。小さな図形は大きな図形と異なる設定を持つ。具体的な定義については、添付のコード(下記)を参照のこと。あるいは、このコードは他のサイズ制約を使って実装することもできる。
【0112】
4.形状の幅と高さの比率が、Nである特定の範囲内で一致しない。この実装では、Nは形状の大きさによって異なる。小さいサイズと大きいサイズでは設定が異なる。具体的な定義については、添付のコード(下記)を参照のこと。あるいは、このコードは他のサイズ制約を使って実装することもできる。
【0113】
C.ここにある場合、見つかった形状は現在の形状のリングとみなされる。現在の形状が上記の「B」リストのものであれば、現在の形状は腫瘤として保存される。見つかった形状が現在の形状となり、B.1に進む。B.1によって除外されない、現在の形状を囲む他の形状がなくなると、現在の同心円状の画素グラデーションの腫瘤は完成したとみなされる。
【0114】
7.ここまで来れば、見つかったすべての同心円状の画素グラデーション腫瘤のリストがある。現在のフィルター設定に一致する画素グラデーションマスを検索する。
【0115】
A.同心円画素グラデーションマスリストをスキャンして、現在のフィルター仕様を満たす腫瘤を探す。
【0116】
B.上記4.Bで定義されたX、Yパスを使用して、発見された各塊を、その塊の中で発見された各形状に対して異なる色範囲を使用して描画する。オプションとして、上記4.B.で保存したパラメータを表示したり、及び/又は、腫瘤で見つかった形状の平均値を表示したりする。あるいは、特定された腫瘤から選択された形状のみを表示することもできる。
【0117】
上記の擬似コードによって実行されるオペレーションをより完全に理解するには、以下のSoftware1-ASCIIの見出しで提供されるソフトウェアリストを参照することで、理解できる。
【0118】
ラジオミクス-スピキュレーションの定量化/特性評価
【0119】
図18を参照すると、システム10、より詳細には、例えば、クライアント及び/又はサーバ装置12~18のうちの1つ又は複数が、グロースリングのスピキュレーションの定量化又は特性評価(以降では、総称的に、特性評価)を行うことができ、及び/又は、これによって、部分をグロースリングが形成する一連の同心円状のこうしたリング(こうした一連のリングは、特定性又は汎用性を失うことなく従うテキストにおける画素グラデーションマス又はPGM)について、例えば、潜在的な癌性、非癌性(例えば、通常の密度)、又は他の腫瘤を示すものとして、定量化又は特性評価を行うことができる。
図18の方法を実施するためのシステム10、より詳細には装置12~18のプログラミングは、本明細書の教示に照らして当業者の知識の範囲内である。
【0120】
ステップ1800において、図示された方法は、非限定的な例として、例えば
図14において「5」とラベル付けされたグロースリングなど、特徴付けされるグロースリングの周囲を歩行(ウォーキング、Walk)し、その周囲を定義する座標の順序付きリストを生成する。歩行は時計回り方向でも反時計回り方向でもよいが、好ましくは、特徴付けされるグロースリングの全周にわたって一貫して行われる。グロースリングの外周をウォーキングすることは、本明細書の教示に照らして当業者の知識の範囲内である。
【0121】
ステップ1805で、図示の方法は、ステップ1800で生成された座標のリストを座標のグループ(「チャンク」の)に分割する。この分割は、グロースリング外周上の各変曲点のいずれかにある座標のチャンクにリストを分割するように行われる。ここでいう「変曲点」とは、例えば、グロースリングの傾きの符号が変化するグロースリング上の点のことである、例えば、(i)x座標(△x)の増加変化に対するy座標(△y)の増加変化を表すものから、x座標の減少変化に対するy座標の増加変化を表すものへ、より簡潔に言えば、+△y/+△x→+△y/-△xへと変化する;又は、この記号を使い続けるなら、(ii) +Δy/+Δx→-Δy/+Δx;又は、(iii)+Δy/-Δx→+Δy/+Δx;又は(iv)+△y/-△x→-△y/-△x;など、本明細書の教示に照らして当業者の知識の範囲内である。
【0122】
ステップ1810で、図示された方法は、各チャンクをそのスパン対長さの比率に基づいて定量化する。ここで使用されるように、チャンクの「スパン」とは、チャンクの端点間のデカルト座標系上の距離、より口語的に言えば、それらの端点間の「烏の飛ぶような」距離を指す。図示された実施形態では、このスパン又は距離は画素単位で測定されるが、他の実施形態ではこの点で異なる場合がある。一方、チャンクの「長さ」は、チャンクを構成する座標によって定義されるパスに沿って、点から点へと連続して移動して測定された距離の合計である。これもまた、図示の実施形態では画素単位で測定されるが、この点に関しては、他の実施形態では異なる場合がある。
【0123】
当業者には理解されるように、このように定義されるスパン対長さの比率は、0より大きく1以下、すなわち1≦スパン対長さの比率>0であり、直線セグメントを定義するチャンクはスパン対長さの比率=1を有し、直線から逸脱するチャンクはそのような比率がより小さい。
【0124】
ステップ1815において、図示された方法は、それぞれのスパン対長さ比率に従ってチャンクをビニングし、次に、各ビンについて、(i)そのビンに含まれるチャンクの長さを合計し、(ii)その合計が、特徴付けされるグロースリングの全周囲の何パーセントを構成するかを決定する。この点に関して他の実施形態は異なるかもしれないが、図示の実施形態では、方法はステップ1815において、0~0.01、0.01~0.02、0.02~0.03、...、0.10~0.11、0.11~0.12、0.12~0.13、...0.97、0.98、0.99、1.0であるのスパン対長さ比率を有するチャンクを収集するために100個のビンを用いるが、これらはすべて非限定的な例である。
【0125】
ステップ1820において、図示された方法は、ステップ1815で生成されたパーセンテージを、ステップ1815でそれらのパーセンテージが関連付けられていたビンのスパン対長さ比率に基づいてスーパービンに収集する(すなわち、ビニングする)。ステップ1820のスーパービンの数は、(ステップ1815の)ビンの数より小さく、図示された実施形態では、10倍小さいが、他の実施形態では、この点で異なる可能性がある。さらに、図示された実施形態では、スーパービンは、それぞれ、0~0.1、0.1~0.2、0.2~0.3、0.3~0.4、0.4~0.5、0.5~0.6、0.6~0.7、0.7~0.8、0.8~0.9、0.9~1.0のスパン対長さ比率に関連しているが、再度述べると、他の実施形態はこの点で異なる可能性がある。上記の例を続けると、ステップ1820において、図示された方法は、ステップ1815のビン0-0.01、0.01~0.02、0.02~0.03...0.09~0.1のパーセンテージを0~0.1の比率のスーパービンに;、0.10~0.11、0.11~0.12、0.12~0.13...0.19~0.2のパーセンテージを0.1~0.2の比率のスーパービンに収集することができ、以下同様であり、これらは、非限定的な例である。もちろん、いくつかの実施形態では、後述するステップ1825で使用されるスーパービンにそれぞれのパーセンテージを収集するだけである。
【0126】
ステップ1825で、図示の方法は、少なくとも選択されたスーパービンのそれぞれのパーセンテージを合計する。ここでは、それらは、スパン対長さの比率が0.6~0.7、0.7~0.8、0.8~0.9、0.9~1.0に関連するスーパービンであるが、他の実施形態では、使用されるスーパービンの数とそれによって表される比の両方に関して、この点で異なる可能性がある。それらのパーセンテージは、一緒になって、特徴付けされているグロースリングを「定量化」し、記憶、表示、及び/又はさらなる処理の目的のために、それぞれ別々の変数(又は他のデータ構造)として維持することができ、又はそれらは、スピキュレーション「値」と呼ばれる単一の数値を形成するために、互いに一緒に付加することができる。例えば、比率0.6~0.7、0.7~0.8、0.8~0.9、0.9~1.0にそれぞれ関連するスーパービンについて、ステップ1825でパーセント15%、5%、10%、3%が合計された場合、それらのパーセントを付加して(必要に応じて2桁又は他の統一フォーマットにパディングして)、スピキュレーション値「15051003」を形成することができる。
【0127】
ステップ1830で、図示の方法はステップ1825の定量化に基づいてそのグロースリングを特徴付ける。これは、選択されたスーパービン(例えば、0.6~0.7、0.7~0.8、0.8~0.9及び0.9~1.0のスパン対長さの比率に関連するビン)の各々のパーセント合計を、既知の形態の組織、例えば、癌組織、非癌組織などのグロースリングについて、同様の方法(例えば、ステップ1800~1825の実施を通して)で生成された対応する合計と比較することによって行われる。比較が良好な場合、グロースリングはその形態である可能性があると特徴付けられる。比較は、比較された各パーセンテージの間に数値的な同一性を要求するという意味で厳密なものとすることもできるし、又は、例えば、既知の形態の組織がそれぞれのスパン対長さの比率の値の範囲と関連付けられるような、範囲に基づくものとすることもできる。
【0128】
ステップ1835に反映されるように、スピキュレーション定量化又は特徴付けは、関心のあるPGM(又はそれ以外)とともに表示され得、それは、議論されるように、グロースリング(又は「ポリゴン」)及び/又はPGM(又は「マルチポリゴンマス」)の再シェーディング、カラー化及び/又は他の表示強化を通知し得る、例えば、
図7に関連して、より詳細かつ非限定的な例として、システム10は、このような定量化又は特徴付けの関数として、このような強調の性質及び/又は度合いを変化させることができ、すべて本明細書の教示に照らして当業者の知識の範囲内である。
【0129】
さらに非限定的な例として、このようなシステム10は、ある色又は色範囲では、潜在的に癌組織に特徴的なスピキュレーションを有するグロースリングを有するPGMをハイライトし、別の色又は色範囲では、非癌組織に特徴的なスピキュレーションを有するグロースリングで構成されるPGMをハイライトすることができる。
【0130】
このようなスピキュレーションの特徴付けは、その代わりに、又はそれに加えて、例えば、
図5に関連して上述したように、このようなグロースリング(又はポリゴン)の作成及びソート、及び/又は例えば、
図6に関連して上述したように、PGM(又はマルチポリゴンオブジェクト)の組立を通知することができ、その結果、より詳細には、非限定的な例として、システム10は、そのグロースリングのスピキュレーションの特徴付けに応じて、PGMの外側の境界としてグロースリングを選択したり、逆に無視したりすることができる。
【0131】
さらなる非限定的な例として、このようなシステム10は、そうでなければ周囲がポリゴンPGMの外側の境界を形成するであろうグロースリングの中から、そのスピキュレーション特徴づけが潜在的に癌組織を示す可能性が最も高いグロースリング(もしあれば)を選択することができる。このようなスピキュレーション特徴づけの使用は、PGMの強調及び表示だけでなく、(i)それぞれの減衰係数及び他の尺度(例えば、寸法、密度、白さ/暗さなど)にも影響を与えることができる(例えば、
図7に関連して上述し、「実施例」と題する節に関連して上述したように)、及び(ii)腫瘤間の検索及び比較(例えば、
図8に関連して上述したように)にも影響を与えることができ、これらは、すべて非限定的な例によるものであり、すべて本明細書の教示に照らして当業者の知識の範囲内である。
【0132】
図18に示され、それに関連して上述された方法のより完全な理解は、以下のmarginSpiculationCode-ASCIIの見出しの下に提供されたソフトウェアのリストを参照することによって達成されるであろう。
【0133】
ラジオミクス - 正規化画素密度(「NPD」)。
【0134】
図19を参照すると、システム10、より詳細には、例えば、クライアント及び/又はサーバ装置12~18のうちの1つ以上は、その正規化画素密度(NPD)を決定することによって、すなわち、放射線画像、超音波画像又は他の画像の関心領域内の画素の強度に対するグロースリング内の画素の平均強度のパーセンタイル・ランキングを決定することによって、グロースリングを定量化することもできる。
図19の方法を実施するためのシステム10、より詳細には装置12~18のプログラミングは、本明細書の教示に照らして当業者の知識の範囲内である。
【0135】
図19に示す実施形態及び後述する実施形態では、関心領域は、その一部を形成する放射線画像、超音波画像又はその他の画像全体ではないとしても、グレースケールに変換されているものと仮定する。他の実施形態では、
図19の方法を実行する前にそのような変換を実行することができる。さらに他の実施形態は、後述するグレースケール強度値の代わりに、関心領域又はその一部を形成する画像に含まれるRGB又は他の画素値から直接計算される強度値を使用してその方法を実行してもよく、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0136】
ステップ1900において、図示の方法は、ユーザによって選択された関心領域(本明細書では「ビットマップ」と呼ばれることもある)の画素強度を正規化する。これは、処理される放射線画像、超音波画像又は他の画像全体とすることができるが、より典型的には、その教示に鑑みて当業者の知識の範囲内であるように、マウス、タッチスクリーン又は他の方法によってユーザによって特定される領域である。これに代えて又はこれに加えて、関心領域/ビットマップは、図示された方法論の一部として、例えば、PGM内の全てのグロースリングに対するNPDの決定と関連して、又は他の方法で、やはり、本明細書の教示に鑑みて当業者の知識の範囲内であるように、自動的に(すなわち、システム10の操作によって)選択され得る。
【0137】
ビットマップ内の画素強度の正規化は、本明細書の教示に照らして当業者の知識の範囲内であり、非限定的な例として、以下によって実行することができる:(i)ビットマップ内のすべての画素の強度を調査して、強度の最小値と最大値を特定する、(ii)それらの最小値と最大値を0~255の範囲に拡張するスケーリングファクタとオフセットを決定し(又は、実装で使用されるような他の正規化ターゲット)、(iii)そのファクタとオフセットをROI内の画素の強度値に適用して正規化する。当業者の知識の範囲内の他の正規化技術を、代わりに又は追加して使用することができる。
【0138】
ステップ1905において、図示された方法は、ROI内に全体ではないにしても少なくとも部分的に位置する関心グロースリング(GROI)内の画素の平均強度を決定する。GROIは、その教示に鑑みて当業者の知識の範囲内であるように、マウス、タッチスクリーン、又は他の方法によってユーザによって特定することができる。これに代えて、又は、これに加えて、GROIは、図示された方法論の一部として、例えば、ROI内の全てのグロースリングのNPDの決定に関連して、自動的に(すなわち、システム10の操作によって)選択され得るが、これもまた、本明細書の教示に照らして当業者の知識の範囲内である。
【0139】
GROI内の画素強度の平均強度を決定することは、本明細書の教示に鑑みて当業者の知識の範囲内であり、非限定的な例として、(正規化ステップ1900に続いて)GROI内の画素の強度を合計し、その合計をそれらの画素のカウントで割ることによって実行することができる。当業者の知識の範囲内の他の平均化技術を、代わりに又は追加して使用することができる。
【0140】
ステップ1910において、図示された方法は、ステップ1905において決定された平均がROI内の画素の正規化された強度に対して相対的であるパーセンタイル・ランキングを決定する。このようなパーセンタイル・ランキング(a/k/a正規化画素密度又はNPD)を決定することは、本明細書の教示に照らして当業者の知識の範囲内であり、非限定的な例として、以下により実行することができる:ビットマップ内のすべての画素の正規化された強度を調査し、「白さ」が最も強いX線及び他の撮像モダリティの場合には、ステップ1905で決定された平均強度下回る(又は、当該平均強度である)強度を有するものをカウントすることによって、又は逆に、「暗さ」が最も強い超音波及び他のモダリティの場合には、平均強度を上回る(又は、当該平均強度である)強度を有するものをカウントする。当業者の知識の範囲内の他のパーセンタイル・ランキング技術を、代わりに又は追加して使用することができる。
【0141】
グロースリングのNPDは、単独で、又は
図18に関連して議論されたスピキュレーションの定量化/特徴付け、
図20に関連して議論される相対的中心化距離パーセント、
図21~
図22に関連して議論されるバランス決定、及び/又は
図23に関連して議論される度合いの多形性と関連して、そのグロースリング又はそれが一部を形成するPGMを、例えば潜在的に癌性、非癌性(例えば、通常の密度)、又は、他の腫瘤を示すものとして、特徴付けて通知することができる。
【0142】
したがって、例えば、図示の方法は、グロースリングのNPDを、既知の形態の組織、例えば、癌組織、非癌組織などのグロースリングについて同様の方法で(例えば、ステップ1900~ステップ1910の実施を通じて)生成されたNPDと比較することができる。比較が良好な場合、グロースリングはその形態である可能性があると特徴づけることができる。比較は、比較された各値の間に数値的な同一性を要求するという意味で厳密なものとすることもできるし、又は、例えば、既知の形態の組織がNPD値の範囲と関連している場合のように、範囲に基づくものとすることもできる。
【0143】
ステップ1915に反映されるように、上述のように決定されたNPDは、対象のグロースリング(又はそれ以外)とともに表示され得、それは、例えば、
図7に関連して、議論されたように、グロースリング(又は「ポリゴン」)及び/又はPGM(又は「マルチポリゴンマス」)の再シェーディング、カラー化及び/又は他の表示強化を通知し得るものであり、そして、その結果、より詳細には、非限定的な例として、システム10は、GRのNPDの関数として、その一部を形成するGR又はPGMのそのような強調の性質及び/又は度合いを変化させることができ、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0144】
さらに非限定的な例として、このようなシステム10は、ある色又は色範囲では、NPDがある数値範囲に入るグロースリングを有するGRをハイライトし、別の色又は色範囲では、NPDが別のそのような範囲に入るGRをハイライトすることができる。
【0145】
グロースリングのNPDは、その代わりに、又はそれに加えて、例えば、
図5に関連して上述したように、その作成及び/又はそのようなグロースリング(又はポリゴン)のソーティング、及び/又は例えば、
図6に関連して上述したように、PGM(又はマルチポリゴンオブジェクト)の組み立てを通知することができ、その結果、より詳細には、非限定的な例として、システム10は、それらのグロースリングのNPDに応じて、PGMのメンバーとしてグロースリングを選択したり、逆に無視したりすることができる。
【0146】
さらに非限定的な例として、このようなシステム10は、そうでなければ外周がマルチポリゴンPGMの外側の境界を形成するであろうグロースリングの中から選択するために、NPDを用いることができる。このようなNPDの使用は、PGMの強調及び表示だけでなく、以下にも影響を与えることができる:(i)例えば、
図7に関連して上述し、「実施例」と題する節に関連して上述したように、それぞれの減衰係数及び他の尺度(例えば、寸法、密度、白さ/暗さなど)、及び、(ii)例えば、
図8に関連して上述したように、腫瘤間の検索及び比較、そして、これらは、すべて非限定的な例によるものであり、すべて本明細書の教示に照らして当業者の知識の範囲内である。
【0147】
図19に示され、それに関連して上述された方法のより完全な理解は、以下のNormalizedPixelDensity-ASCIIの見出しで提供されるソフトウェアリストを参照することによって達成されるであろう。
【0148】
ラジオミクス-相対中心化距離パーセント(RCDP)
【0149】
図20を参照すると、システム10、より詳細には、例えば、クライアント及び/又はサーバ装置12~18のうちの1つ又は複数が、対象のPGMの相対中心化距離パーセント(RCDP)-すなわち、PGMの中心とそれを構成する最も強いグロースリングの中心との間の距離-を定量化することができ、ここで、その距離は、異なる病変/PGMサイズにわたる比較を促進するために正規化される。
【0150】
本節において、特異性又は一般性を失うことなく使用されるように、画素グラデーションマス及びPGMという用語は、一連の同心円形状のグロースリング、例えば、その組立が、例えば、
図6に関連して上述されたタイプのものを指す。
図20の方法を実施するためのシステム10、より詳細には、装置12~18のプログラミングは、本明細書の教示に照らして当業者の知識の範囲内である。
【0151】
図20に示す実施形態及び後述する実施形態では、対象のPGMは、そのPGMが一部を構成する放射線画像、超音波画像又はその他の画像全体ではないとしても、グレースケールに変換されているものと仮定する。他の実施形態では、
図20の方法を実行する前にそのような変換を実行することができる。さらに他の実施形態は、後述するグレースケール強度値の代わりに、対象のPGM又はその一部を形成する画像に含まれるRGB又は他の画素値から直接計算される強度値を使用してその方法を実行してもよく、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0152】
ステップ2000において、図示の方法は、対象のPGMの腫瘤の中心の位置、ならびにそのPGMの最長及び最短の直径を決定する。これは、その教示に鑑みて当業者の知る範囲であるように、マウス、タッチスクリーン又は他の方法によってユーザによって特定されたPGMであり得る。これに代えて、又は、これに加えて、対象のPGMは、例示された方法論の一部として、例えば、システム10によって特定され及び/又は表示される1つ以上のPGMの中心化密度(RCDP)の決定に関連して、やはり、本明細書の教示に照らして当業者の知識の範囲内であるように、自動的に(すなわち、システム10の操作によって)選択され得る。
【0153】
以下の議論では、対象PGMの腫瘤の中心の位置をOMCP(Outside Margin Centralized Point)と呼ぶ。そのPGMの最長径は、OMSLD(Outside Margin Shape Longest Diameter)と呼ぶ。そのPGMの最短直径は、OMSSD(Outside Margin Shape Shortest Diameter)と呼ぶ。
【0154】
対象のPGMの腫瘤の中心を求めることは、本明細書の教示に照らして当業者の知識の範囲内であり、本明細書の教示に一致して適合されるように、当技術分野で公知の多数の技法のいずれかによって実行することができる。図示された実施形態では、腫瘤の中心の決定は、PGMの外側の境界内に横たわる全ての画素の強度を考慮に入れる(例えば、それらの画素が、そのPGMを構成する1つ以上の他の同心円のグロースリング内にさらに存在するかどうかに関係なく)が、他の実施形態では、それらの画素のサブセット(例えば、ユーザが選択した内側の送信塩のグロースリング内の画素又は他の画素)のみを考慮に入れることができる。
【0155】
対象のPGMの最長及び最短の直径を求めることは、本明細書の教示に照らして当業者の知識の範囲内であり、非限定的な例として、PGM内に収まる最小の円とPGMを囲む最大の円の両方を求めることによって実行できる。前者の直径はOMSSDを定義し、後者の直径はOMSLDを定義する。OMSSD及びOMSLDを決定するために、本明細書の教示に従って適応された当業者の知識の範囲内の他の技術を、代わりに又は追加して使用できることが理解されよう。
【0156】
ステップ2005において、図示の方法は、関心のあるPGM内で最も強度の高いグロースリングを特定する。X線写真画像等(すなわち、「白さ」が最も高い強度を表す医療用画像)の場合、これは、そのPGM内で最も高い(最も白い)平均画素強度を有するグロースリングを見つけることを必要とする。超音波画像等(すなわち、「暗さ」が最も高い強度を表す医療用画像)の場合、これは、最も低い(最も暗い)平均強度を有するものを見つけることを必要とする。このようなグロースリングを見つけることは、本明細書の教示を考慮すれば、当業者の常識の範囲内である。
【0157】
ステップ2010において、図示の方法は、ステップ2005で特定されたグロースリングの腫瘤の中心の位置を求める。このような腫瘤の中心を求めることは、本明細書の教示に照らして当業者の常識の範囲内であり、本明細書の教示に適合するように当技術分野で知られている多数の技術のいずれかによって実行することができる。以下の数学的関係において、その位置は、最密ポリゴン中心点(又はDPCP)と呼ばれる。
【0158】
ステップ2015において、図示の方法は、ステップ2000及び2005において見出された腫瘤の中心間の距離DPの関数として、すなわちそれぞれOMCP及びDPCPの関数として、及び、対象のPGMの最大径及び最小径の関数として、すなわちOMSLD及びOMSSDの関数として、対象のPGMの相対中心化距離パーセント(RCDP)を計算する。より詳細には、RCDPを数学的関係に基づいて決定する:
【0159】
RCDP=DP/(OMSLD+OMSSD)
【0160】
ここで、
【0161】
DP=OMCP-DPCP
【0162】
図示された方法の文脈におけるこのような数学的関係の実施及び実行は、本明細書の教示に照らして当業者の知識の範囲内である。
【0163】
PGMのRCDPは、単独で、又は
図18に関連して議論されたスピキュレーション定量化/特徴付け、
図19に関連して議論された正規化画素密度、
図21~
図22に関連して議論されるバランス決定、及び/又は
図23に関連して議論される多形性と組み合わせて、例えば、潜在的な癌性、非癌性(例えば、自然密度)、又は他の腫瘤を示すものとしてそのPGMを特徴付けることを知らせることができ、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0164】
従って、例えば、図示された方法は、PGMのRCDPを、既知の形態の組織、例えば、癌組織、非癌組織などのPGMと同様に(例えば、ステップ2000~ステップ2015の実施によって)生成されたRCDPと比較することができる。比較が良好である場合、対象のPGMはその形態である可能性があると特徴付けることができる。比較は、比較された各値の間に数値的な同一性を要求するという意味で厳密なものとすることもできるし、例えば、既知の形態の組織がRCDP値の範囲と関連している場合のような範囲に基づくものとすることもできる。
【0165】
ステップ2020に反映されるように、上述のように決定された相対中心化距離パーセント(RCDP)は、例えば、
図7に関連して、対象のPGM(又はそれ以外)とともに表示され得、それは、議論されたように、グロースリング(又は「ポリゴン」)及び/又はPGM(又は「マルチポリゴンマス」)の再シェーディング、カラー化及び/又は他の表示強化を通知し得るものであり、その結果、より詳細かつ非限定的な例として、システム10は、対象のPGMのRCDPの関数として、その一部を形成するGR又はPGMのそのような強調の性質及び/又は程度を変化させることができ、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0166】
さらに非限定的な例として、このようなシステム10は、ある色又は色範囲において、ある数値範囲に該当するRCDPを有するPGMをハイライトし、別の色又は色範囲において、RCDPが別のそのような範囲に該当するPGMをハイライトすることができる。
【0167】
PGMのRCDPは、その代わりに、又はそれに加えて、例えば
図5に関連して上述したように、その作成及び/又はそのようなグロースリング(又はポリゴン)のソーティング、及び/又は、例えば
図6に関連して上述したように、PGM(又はマルチポリゴンオブジェクト)の組立を通知することができ、その結果、より詳細には、非限定的な例として、システム10は、そのような選択から生じるであろうRCDPに応じて、PGMのメンバーとしてグロースリングを選択したり、逆に無視したりすることができる。
【0168】
図20に示され、それに関連して上述された方法のより完全な理解は、以下の見出しcentralizedDensityCode-ASCIIの下で提供されるソフトウェアリストを参照することによって達成され得る。
【0169】
ラジオミクス-バランス決定
【0170】
図21を参照すると、システム10、より詳細には、例えば、クライアント及び/又はサーバ装置12~18のうちの1つ又は複数が、対象のPGMのバランス、すなわち、X軸、Y軸、及び組み合わされたX/Y軸を横切るPGMを構成する画素の対称性、及びそれによって、そのPGMによって撮像される腫瘤又は他の組織の対称性を定量化する(又はその度合いを決定する)ことができる。理解されるように、以下に説明する方法は、グロースリングのバランスの度合いを決定することにも適用することができる。
【0171】
本節において、特異性又は一般性を失うことなく使用されるように、画素グラデーションマス及びPGMという用語は、一連の同心円形状のグロースリング、例えば、その組立が、例えば、
図6に関連して上述されたタイプのものを指す。
図20の方法を実施するためのシステム10、より詳細には、装置12~18のプログラミングは、本明細書の教示に照らして当業者の知識の範囲内である。
【0172】
図21に示す実施形態及び後述する実施形態では、関心対象のPGMは、そのPGMが一部を構成する放射線画像、超音波画像又はその他の画像全体ではないとしても、グレースケールに変換されているものと仮定する。他の実施形態は、
図20の方法を実行する前にそのような変換を実行することができる。さらに他の実施形態は、後述するグレースケール強度値の代わりに、対象のPGM又はその一部を形成する画像に含まれるRGB又は他の画素値から直接計算される強度値を使用してその方法を実行してもよく、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0173】
ステップ2100において、図示の方法は、対象のPGMのバウンディングボックスを決定する。これは、その教示内容に照らして当業者の知識の範囲内であるが、マウス、タッチスクリーン、又は他の方法によってユーザによって特定されるPGMであり得る。これに代えて、又は、これに加えて、対象のPGMは、例示された方法論の一部として、例えば、システム10によって識別及び/又は表示される1つ又は複数のPGMのバランスの度合いの決定に関連して(すなわち、システム10の操作によって)、自動的に選択され得るが、これもまた、本明細書の教示に照らして当業者の知識の範囲内である。
【0174】
対象のPGMのバウンディングボックスを求めることは、本明細書の教示に照らして当業者の知識の範囲内であり、本明細書の教示に従って適合されるように、当技術分野で公知の多数の技法のいずれかによって実行することができる。図示の実施形態では、バウンディングボックスの決定は、PGMの外側の境界内に存在するすべての画素の強度を考慮するが、他の実施形態では、それらの画素のサブセット(例えば、ユーザが選択した内側の同心円のグロースリング内の画素など)のみを考慮することができる。
【0175】
ステップ2105で、図示の方法はバウンディングボックスを等しい大きさの領域に分割する。付属
図22AのA、B、C、Dとラベル付けされた領域を参照されたい。各領域は、順に、等しい大きさのサブ領域に分割される。付属
図22Aの1~16とラベル付けされたサブ領域を参照。図示された実施形態は、4と4、すなわち、領域ごとに4つの領域と4つのサブ領域の分割を企図しているが、他の実施形態は、非限定的な例として、例えば、8つの領域と16のサブ領域を利用するなど、この点で変化してもよい。以下の議論において、領域及びサブ領域は、一般性又は特異性を失うことなく、それぞれ、クアドラント及びサブクアドラントと呼ばれる。
【0176】
さらに、図示された実施形態では、クアドラント及びサブクアドラントは、対象のPGMが同定された放射線画像、超音波画像、又は他の画像のX軸及びY軸と位置合わせされるが、他の実施形態では、それらは、対象のPGMの主モーメントに基づいて、又は他の方法で、X軸及びY軸と位置合わせされてもよく、すべては、本明細書の教示に鑑みて当業者の知識の範囲内である。
【0177】
ステップ2105で企図されるような対象のPGMの分割は、本明細書の教示にかんがみて、当業者の知識の範囲内である。
【0178】
ステップ2110において、図示の方法は、各サブクアドラント1~16内の画素をカウントする。図示された実施形態では、これは、非限定的な例として、閾値強度レベル、例えば、放射線画像等(すなわち、「白さ」が最も高い強度を表す医療用画像)については10又は25より上、又はそのような強度レベル、例えば、超音波画像等(すなわち、「暗さ」が最も高い強度を表す医療用画像)については245又は230より下の画素のみをカウントすることを企図している、ただし、他の実施形態では、異なる閾値及び/又は複数の閾値を利用してもよく(この場合、例えば、このようなカウントは、複数の閾値強度内の画素に関して行われる)、すべては、本明細書の教示に鑑みて、当業者の知識の範囲内である。
【0179】
ステップ2115において、図示の方法は、各サブクアドラント内の画素のカウント(適用される閾値(複数可)を超える/下回る/範囲以内)を、対称線としてX軸を横切る、対称線としてY軸を横切る、及び対称線としてX軸及びY軸を組み合わせた線を横切る、他の各サブクアドラント内の画素と比較する。
【0180】
これは、クアドラントAのサブクアドラント1、2、5、6の画素のそれぞれに対する比較に関して、次のように説明される:
【0181】
(i)Y軸を横切る対称性に対するクアドラントBのサブクアドラント3、4、7、8の画素(
図22Bにおいて、これら2つのクアドラントを区切る暗い垂直線によって示される)。その図面の曲線で示されるように、具体的な比較は以下の通りであり、各数字はサブクアドラント、「v」は比較を示す:
【0182】
1v4
【0183】
2v3
【0184】
5v8
【0185】
6v7
【0186】
(ii)X軸を横切る対称性に対するクアドラントCのサブクアドラント9、10、13、14の画素(
図22Cにおいて、これら2つのクアドラントを区切る暗い水平線によって示される)。その図面の曲線で示されるように、具体的な比較は以下の通りであり、各数字はサブクアドラント、「v」は比較を示す:
【0187】
5v9
【0188】
6v10
【0189】
1v13
【0190】
2 v 14
【0191】
(iii)X軸とY軸を組み合わせた対称性に対するクアドラントDのサブクアドラント11、12、15、16の画素(
図22Dにおいて、これら2つのクアドラントを区切る暗色の対角線によって示される)。その図面の曲線で示されるように、具体的な比較は以下の通りであり、各数字はサブクアドラント、「v」は比較を示す:
【0192】
6v11
【0193】
2v15
【0194】
1v16
【0195】
5v12
【0196】
各比較は減算であり、別の言い方をすれば、各比較は、比較されたサブクアドラントの各々における画素数(各々、適用される閾値(複数可)を超える/下回る/その範囲内である)の差を決定する。いくつかの実施形態では、比較はさらに、各減算の結果の絶対値を取ることを含む。
【0197】
クアドラントAのサブクアドラントとクアドラントB、C及びDのサブクアドラントとの比較については、上記にて詳述した。同様に、ステップ2115では、クアドラントBのサブクアドラントとクアドラントC及びDのサブクアドラントとの比較、及びクアドラントCのサブクアドラントとDのサブクアドラントとの比較を行うが、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0198】
上記のように画素数を比較することは、本明細書の教示に照らして当業者の知識の範囲内である。
【0199】
ステップ2120において、図示の方法は、ステップ2115において実行された比較の結果を合計する。その結果得られる値は、対象のPGMのバランスの度合い、及び、それによって撮像される腫瘤又は他の組織の測定値又は定量化である。
【0200】
PGMのバランスの度合いは、単独で、又は
図18に関連して議論されたスピキュレーション定量化/特徴付け、
図19に関連して議論された正規化画素密度、
図20に関連して議論された相対的中心化距離パーセント、及び/又は
図23に関連して議論された多形性の度合いと関連して、そのPGMが、例えば、潜在的に癌性、非癌性(例えば、通常の密度)、又は他の腫瘤を示すものとして特徴づけることを通知することができ、すべて本明細書の教示に照らして当業者の知識の範囲内である。
【0201】
従って、例えば、例示された方法は、対象のPGMのバランスの度合いを、既知の形態の組織、例えば、癌組織、非癌組織などのPGMについて同様の方法で(例えば、ステップ2100~215の実行を通して)生成されたバランスの度合いと比較することができる。比較が良好な場合、グロースリングはその形態である可能性があると特徴付けることができる。比較は、各比較値の間に数値的な同一性を要求するという意味で厳密なものとすることもできるし、例えば、既知の形態の組織がバランスの度合いの範囲と関連している場合のように、範囲に基づくものとすることもできる。
【0202】
ステップ2125に反映されるように、上述のように決定されたバランスの度合いは、対象のPGM(又はそれ以外)とともに表示され得、それは、例えば、
図7に関連して、議論されるように、グロースリング(又は「ポリゴン」)及び/又はPGM(又は「マルチポリゴンマス」)の再シェーディング、カラー化及び/又は他の表示強化を通知し得るものであり、その結果、より詳細には、非限定的な例として、システム10は、PGMのバランスの度合いの関数として、その一部を形成するGR又はPGMのそのような強化の性質及び/又は度合いを変化させることができ、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0203】
さらに非限定的な例として、このようなシステム10は、ある色又は色範囲において、ある数値範囲に入るバランス度合いを有するPGMをハイライトし、別の色又は色範囲において、バランス度合いが別のそのような範囲に入るPGMをハイライトすることができる。
【0204】
PGMのバランスの度合いは、その代わりに、又はそれに加えて、例えば、
図5に関連して上述したように、その作成及び/又はそのようなグロースリング(又はポリゴン)のソーティング、及び/又は例えば、
図6に関連して上述したように、PGM(又はマルチポリゴンオブジェクト)の組み立てを通知することができ、その結果、より詳細には、非限定的な例として、システム10は、それらのグロースリングによって全体としてPGMに付与されるバランスの結果的な度合いに応じて、PGMのメンバーとしてグロースリングを選択したり、逆に無視したりすることができる。
【0205】
さらに非限定的な例として、このようなシステム10は、そうでなければ周囲がマルチポリゴンPGMの外側の境界を形成するであろうグロースリングの中から選択するために、バランスの度合いを用いることができる。このようなバランスの度合いの使用は、PGMの強調及び表示だけでなく、(i)
図7に関連して上述し、「実施例」と題する節に関連して上述したように、それぞれの減衰係数及び他の尺度(例えば、寸法、密度、白さ/暗さなど)及び(ii)例えば、
図8に関連して上述したように、腫瘤間の検索及び比較にも影響を与えることができ、これらは、すべて非限定的な例によるものであり、すべて本明細書の教示に照らして当業者の知識の範囲内である。
【0206】
図21~22に示され、それに関連して上述された方法のより完全な理解は、以下のlesionBalanceCode-ASCIIの見出しの下に提供されたソフトウェアのリストを参照することによって達成されるであろう。
【0207】
ラジオミクス-多形性判定
【0208】
図23を参照すると、システム10、より詳細には、例えば、クライアント及び/又はサーバ装置12~18のうちの1つ又は複数が、対象領域(ROI)及び/又は関心PGMの多形性を定量化する(又はその度合いを決定する)ことができる。多形性は、対象のROI又は対象のPGMにおけるグロースリングの総カウント数である。
【0209】
本節において、特異性又は一般性を失うことなく使用されるように、画素グラデーションマス及びPGMという用語は、一連の同心円形状のグロースリング、例えば、そのアセンブリが、例えば、
図6に関連して上述されたタイプのものを指す。
図20の方法を実施するためのシステム10、より詳細には、装置12~18のプログラミングは、本明細書の教示に照らして当業者の知識の範囲内である。
【0210】
ステップ2300において、図示の方法は、対象のROI又はPGM内のグロースリングの数をカウントする。これは、その教示に照らして当業者の知識の範囲内であるように、マウス、タッチスクリーン、又は他の方法によってユーザによって特定されるROI又はPGMであり得る。これに代えて、又は、これに加えて、対象のROI又はPGMは、図示された方法論の一部として、例えば、システム10によって特定され及び/又は表示される1つ以上のPGMのバランスの度合いを決定することに関連して、(すなわち、システム10の操作によって)自動的に選択され得るが、これもまた、本明細書の教示に鑑みて当業者の知識の範囲内である。
【0211】
対象のROI又はPGM内のグロースリングをカウントすることは、本明細書の教示に照らして当業者の知識の範囲内であり、本明細書の教示に従って適合されるように、当技術分野で公知の多数の技法のいずれかによって実行することができる。図示の実施形態では、例えば、これは、ソフトウェア内で採用されているデータ構造を調査し、対象のROI/PGM内にある境界を有するGRの数をカウントすることによって達成される。いくつかの実施形態では、カウントすることは、指定された特性、例えば、閾値を超える平均画素強度などを有するGRに限定されるが、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0212】
PGMの多形性の度合いは、単独で又は
図18に関連して議論されたスピキュレーションの定量化/特徴付け、
図19に関連して議論された正規化画素密度、
図20に関連して議論された相対的中心化距離パーセント、及び/又は
図21~
図22に関連して議論されたバランス決定と関連して、例えば、潜在的に癌性、非癌性(例えば、自然密度)、又は他の腫瘤を示すものとして、そのPGMを特徴付けることを知らせることができ、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0213】
従って、例えば、図示された方法は、対象のPGMの多形性の度合いを、既知の形態の組織、例えば、癌組織、非癌組織などのPGMについて同様の方法で(例えば、ステップ2300の実行を通して)生成された多形性の度合いと比較することができる。比較が良好な場合、グロースリングはその形態である可能性があると特徴付けることができる。比較は、各比較値間の数値的同一性を要求するという意味で厳密なものとすることもできるし、例えば、既知の形態の組織が多形性の度合いの範囲と関連している場合のように、範囲に基づくものとすることもできる。
【0214】
ステップ2305に反映されるように、上述のように決定された多形性の度合いは、対象のROI/PGM(又はそれ以外)とともに表示され得、それは、例えば、
図7に関連して、議論されるように、グロースリング(又は「ポリゴン」)及び/又はPGM(又は「マルチポリゴンマス」)の再シェーディング、カラー化及び/又は他の表示強調を通知し得るものであり、その結果、より詳細には、非限定的な例として、システム10は、対象のROI/PGMの多形性の度合いの関数として、その一部を形成するGR又はPGMのそのような強調の性質及び/又は程度を変化させることができ、これらはすべて、本明細書の教示に照らして当業者の知識の範囲内である。
【0215】
さらに非限定的な例として、このようなシステム10は、ある色又は色範囲において、ある数値範囲に入る多形性の度合いを有するPGMをハイライトし、別の色又は色範囲において、多形性の度合いが別のそのような範囲に入るPGMをハイライトすることができる。
【0216】
PGMの多形性の度合いは、その代わりに、又はそれに加えて、例えば、
図5に関連して上述したように、その作成及び/又はそのようなグロースリング(又はポリゴン)の並べ替え、及び/又は、例えば、
図6に関連して上述したように、PGM(又はマルチポリゴンオブジェクト)の組み立てを知らせることができ、その結果、より詳細には、非限定的な例として、システム10は、それらのグロースリングによって全体としてPGMに付与される多形性の結果的な程度に応じて、PGMのメンバーとしてグロースリングを選択したり、逆に無視したりすることができる。
【0217】
さらなる非限定的な例として、このようなシステム10は、そうでなければマルチポリゴンPGMの外側の境界を形成するであろう外周を有するグロースリングの中から選択するために、多形性の度合いを用いることができる。このような多形性の度合いの使用は、PGMの強調及び表示だけでなく、(i)
図7に関連して上述し、「実施例」と題する節に関連して上述したように、それぞれの減衰係数及び他の尺度(例えば、寸法、密度、白さ/暗さなど)、及び(ii)例えば
図8に関連して上述したように、腫瘤間の検索及び比較にも影響を与えることができ、これらは、全て非限定的な例であり、全て本明細書の教示に鑑みて当業者の知識の範囲内である。
【0218】
図23に示され、それに関連して上述された方法のより完全な理解は、以下の見出しcentralizedDensityCode-ASCIIの下に提供されるソフトウェアリストを参照することによって達成され得る。
【0219】
図18~
図23に示され、これらに関連して上述された方法についてのより完全な理解は、以下のadditionalDensitySupportcode-ASCIIの見出しの下に提供されたソフトウェアのリストを参照することによって達成され得る。
【0220】
ソフトウェア1-ASCII
【0221】
2018年5月31日出願の米国仮特許出願番号62/678,644のDeepLookソースコード
【0222】
以下は、上記疑似コードのC/C++による現在のDeepLookソースコードである。上記の擬似コードおよび以下のコーディングアルゴリズムは、Java、JavaScript、Python、ActionScript、アセンブラ、C#、BASIC、PERL、RUBY、Objective C、PHPを含むがこれらに限定されない、任意のプログラミング言語またはスクリプト言語で開発、作成、および/または記述することができる。
【0223】
Non-Generic header files
DeepLook.h
#pragma once
#include "resource.h"
Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by DeepLook.rc
//
#define IDC_MYICON 2
#define IDB_RedTrafficLight 3
#define IDD_DEEPLOOK_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDC_DEEPLOOK 109
#define IDR_MAINFRAME 128
#define IDI_DeepLookIcons 130
#define IDR_RT_RCDATA1 131
#define IDB_HelpDropdown 132
#define IDB_HelpTrackbars 133
#define IDB_HelpButtons 134
#define IDB_HelpBubble 137
#define IDB_OverlayGrey 139
#define IDB_GSRedTrafficLight 141
#define IDB_OverlayBlue 142
#define IDB_OverlayRed 144
#define IDB_GreenTrafficLight 145
#define IDB_GreyTrafficLight 147
#define IDB_LSWD_L 149
#define IDB_LSWD_S 150
#define IDB_LSWD_W 151
#define IDB_LSWD_D 152
#define IDB_LSWD_Grey 153
#define IDB_OverlayOnGrey 154
#define IDB_Camera27x20 155
#define IDB_OpenControls 156
#define IDB_WhiteCenter 157
#define IDB_MagMinus 158
#define IDB_MagPlus 159
#define IDB_MagMinusPlus 160
#define IDB_BlackWindow38x25 161
#define IDB_OverlayOff 162
#define IDB_OverlayOn 163
#define IDB_BITMAP1 164
#define IDB_BlackCenter 164
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 165
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
C/C++ Code:
#include <afxwin.h>
#include "afxcmn.h"
#include "stdafx.h"
#include <stdio.h>
#include "DeepLook.h"
#include <process.h>
#include <time.h>
#include "atlimage.h"
#include <atlbase.h>
#include <atlstr.h>
#include <comutil.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>
#include <windows.h>
#include <wingdi.h>
#include <windowsx.h>
#include <winUser.h>
#include <CommCtrl.h>
#include <Commdlg.h>
#include <wbemidl.h>
#include <sys/stat.h>
#include <Ddraw.h>
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib,"Comdlg32.lib")
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib,"Ddraw.lib")
#pragma comment(lib,"Dxguid.lib")
using namespace std;
#define MAX_LOADSTRING 100
#define Window_Line_Width 8
#define Window_Top_Bar_Height 31
#define Stop_Light_Bar_Height 22
#define Color_Group_Count 7
#define Max_Color_Count 256
#define Grey_Scale_Colors_4 4
#define Grey_Scale_Shift_4 6
#define Grey_Scale_Colors_8 8
#define Grey_Scale_Shift_8 5
#define Grey_Scale_Colors_16 16
#define Grey_Scale_Shift_16 4
#define Grey_Scale_Colors_32 32
#define Grey_Scale_Shift_32 3
#define Grey_Scale_Colors_64 64
#define Grey_Scale_Shift_64 2
#define Grey_Scale_Colors_128 128
#define Grey_Scale_Shift_128 1
#define Grey_Scale_Colors_256 256
#define Grey_Scale_Shift_256 0
// byte positions
#define Grey_Scale_XY_Path_Byte_Offset 4
#define Percent_Used_XY_Path_Byte_Offset 5
#define X_Center_XY_Path_Byte_Offset 6
#define Y_Center_XY_Path_Byte_Offset 7
#define Ratio_XY_Path_Byte_Offset 8
#define Horiz_Len_XY_Path_Byte_Offset 9
#define Vert_Len_XY_Path_Byte_Offset 10
#define Text_AverageX_XY_Path_Byte_Offset 11
#define Text_AverageY_XY_Path_Byte_Offset 12
#define Text_Horiz_Len_XY_Path_Byte_Offset 13
#define Text_Vert_Len_XY_Path_Byte_Offset 14
#define Contrast_Len_XY_Path_Byte_Offset 15
#define Record_Inc 29
#define Row_Write_Size Record_Inc
#define Column_Write_Size Row_Write_Size
#define Growth_Node_Size (25+4)
#define Header_Contrast_Short_Int_Offset 14
#define Header_Brightest_Pixel_Short_Int_Offset 15
#define Header_Brightest_Shape_Short_Int_Offset 16
#define Header_Brightest_Growth_Node_Short_Int_Offset 17
#define Header_Darkest_Growth_Node_Short_Int_Offset 18
#define Header_Densist_Growth_Node_Short_Int_Offset 19
#define Header_Least_Dense_Growth_Node_Short_Int_Offset 20
#define Header_Most_Layers_Growth_Node_Short_Int_Offset 22
#define Header_Least_Layers_Growth_Node_Short_Int_Offset 24
#define Header_Largest_Pixel_Count_Growth_Node_Short_Int_Offset 26
#define Header_Smallest_Pixel_Count_Growth_Node_Short_Int_Offset 28
#define Start_Layer_Used_Flags_Short_Int_Offset 30
#define No_Color -4
#define Mask_It -3
#define Border_Mark 1000
#define Mark_Still_Good 1000
#define Min_Percent_To_Notice 0.0025
#define Closure_Area 80
#define Closure_Gap 0.09
#define Min_OIO_Pixel_Count 10
#define Max_Shading_Layers_Displayed 20
#define Saved_Layers_Count 19
#define File_Header_Length_Bytes ((2*(Header_Smallest_Pixel_Count_Growth_Node_Short_Int_Offset+2))+(Saved_Layers_Count-2))
#define Write_Out_Buffer_Size 500
#define Max_Objects_Per_Image 100000
#define Max_Row_Nodes_Per_Image 200000
#define Max_Column_Nodes_Per_Image Max_Row_Nodes_Per_Image
#define Image_To_Complex -6
#define Max_OS_Memory_Size 1000000 // 32 meg limit -- total 4,096
#define Max_XY_OS_Memory_Size 4000000
#define Max_XY_Column_Memory_Size 1000000
#define Max_XY_Column_Node_Memory_Size 1000000
#define Max_Growth_Nodes 20000
#define SAVE_SHAPE_GREY_SCALE 100
#define Default_Current_Layer 3 //
#define Default_Current_Pixel_Count 1 // smallest one
#define Default_Current_Whiteness_Percent 750// 75 eighty percent
#define Default_Current_Density_Percent 750 // 75 eighty percent
#define Default_Stop_Layers 3
#define Default_Max_Mass 1
// GN defines
#define XY_Offset 13
#define Child_Offset 21
#define Mag_Buttons_Width 41
#define Traffic_Light_Width 41
#define Traffic_Light_Height 20
#define Green_Light 0
#define Red_Light 1
#define Grey_Light 2
#define Traffic_Light_Count 3
#define Button_Width_And_Height 20
#define Button_Spacing 2
#define Camera_Button_Width 27
#define Box_LSWD_Width 67
#define Buttons_Push_Right 2
#define Button_Space_Mulitplier 2
// AWDL BUTTON WIDTHS
#define Auto_Button_End 20
#define XL_LSWD_End 15
#define XS_LSWD_End 30
#define XW_LSWD_End 50
#define To_Be_Marked_Done 999999
#define Control_Button_Letter_height 12
#define Auto_Button_Width 40
#define Auto_Label_Height 30
#define Control_Button_Top_Spacer 6
#define Control_Button_Row_Height (16+Control_Button_Top_Spacer)
#define Control_Button_Spacer 50
#define Controls_Width ((Control_Button_Spacer*5)+Button_Spacing)
#define W_Width 16
#define D_Width 11
#define WD_Width 22
#define WD_Height 10
#define Background_Black_Box_Width 38
#define Background_Black_Box_Height 25
#define Black_Box_1_xPos_Offset 5
#define Tracker_Bar_YPos (Stop_Light_Bar_Height+Control_Button_Row_Height+Background_Black_Box_Height+(Button_Spacing*2))
#define Control_Buttons_Bottom_Y (Stop_Light_Bar_Height+Control_Button_Row_Height)
#define Auto_Label_Top_Y (Stop_Light_Bar_Height+Control_Button_Row_Height+Auto_Label_Vert_Top_Space)
#define Auto_Label_Bottom_Y (Stop_Light_Bar_Height+Control_Button_Row_Height+Auto_Label_Height+Auto_Label_Top_Y)
#define Slider_Label_Y (Stop_Light_Bar_Height+4)
#define Slider_Black_Box_Text_Y_Pos (Stop_Light_Bar_Height+Control_Button_Row_Height)
#define Auto_Button_Bottom (Stop_Light_Bar_Height+Control_Button_Top_Spacer+Auto_Label_Height+Auto_Label_Vert_Top_Space +14)
#define TB_ID_L 1
#define TB_ID_S 2
#define TB_ID_W 3
#define TB_ID_D 4
#define DL_ID_L 66664
#define DL_ID_MaxMass 66665
#define DL_ID_StopLayer 66666
#define Single_Side_Track_Bar_Width 25
#define Double_Side_Track_Bar_Width 42
#define Track_Bar_Generic_Tics 200.0
#define Track_Bar_Height 227
#define Track_Bar_Text_Width 20
#define Black_Screen_Text_Font_Size_Small 8
#define Black_Screen_Text_Font_Size_Large 12
#define Xtra_Large_Screen_Text_Font_Size_Large 14
#define Black_Box_Text_Font_Size 14
#define Slider_Numbers_Font_Size 10
#define Number_Drop_Down_List_Font_Size 12
#define Label_Font_Size 14
#define Label_Width Control_Button_Spacer
#define Label_Height ((Label_Font_Size*2)+Button_Spacing)
#define Number_Drop_Down_List_Width 40
#define Number_Drop_Down_List_Height 300
#define Number_Drop_Down_List_Window_Height (Label_Height+Number_Drop_Down_List_Font_Size+10)
#define Drop_List_Vert_Space 14
#define Density_Percent_Garbage_Value_Split 300 // 30
#define Density_Garbage_Value_Split 800
#define Auto_Label_Vert_Top_Space 48 //16//50
#define X_Off_Screen -10000
#define WDL_Text_Length 100
#define Machine_Code_Char_Length 8
// thread states
#define Thread_Idle -1
#define Thread_Has_Data_To_Process -2
#define Save_Draw_Rectangle_Space 10
#define Max_Key_Length 700
#define No_Overlay 1
#define Overlay_Only 2
#define Overlay_And_Grey 3
#define Overlay_Color_Grey 0
#define Overlay_Color_Blue 1
#define Overlay_Color_Red 2
#define Overlay_Color_Count 3
#define Overlay_Only_Grey 250
#define yPos_Help_Q 0
#define XPos_Offset_Q_Mark (Box_LSWD_Width+1)
#define Question_Mark_Width 6
#define Question_Mark_Height 8
#define Min_Window_Size 325
#define Max_Window_Size 800
#define Help_Window_Width 928
#define Help_Window_Height 185
#define Help_Window_Height_Two_Rows 374
#define Help_Dropdowns_Window_Width 465
#define Help_Dropdowns_Window_Height 224
#define xPos_Help_1 18
#define xPos_Help_2 249
#define xPos_Help_3 483
#define xPos_Help_4 714
#define YPos_Help 32
#define Help_Width 90
#define Help_Height 90
#define Mag_Minus 0
#define Mag_Plus 1
#define Mag_Minus_Plus 2
#define Mag_Button_Count 3
#define Max_Button_Click_Count 4
#define Ypos_Offscreen_Negative_Offset -1000
#define Min_Thread_Process_Size (Min_Window_Size/4)
int realMinWindowSize = Min_Window_Size;
int mapAreaWidth = realMinWindowSize;
int mapAreaHeight = mapAreaWidth;
int windowTopBarHeight = 0;
int windowBorderWidth = 0;
int yPosOffScreen = Ypos_Offscreen_Negative_Offset;
int threadMemMode = 2;
#define WD_Slider_Numbers_xPos ((magWidthHightInc[magButtonClickCount].width+Black_Box_1_xPos_Offset)+Single_Side_Track_Bar_Width+1)
#define Slider_Numbers_yPos (Tracker_Bar_YPos+8)
char *numbersChar = (char *)"10\n\n9.0\n\n8.0\n\n7.0\n\n6.0\n\n5.0\n\n4.0\n\n3.0\n\n2.0\n\n1.0\n\n0";
char *layersChar = (char *)"20\n19\n18\n17\n16\n15\n14\n13\n12\n11\n10\n9\n8\n7\n6\n5\n4\n3\n2\n--\n--";
char *mostLeast = (char *)"M\no\ns\nt\n\n\n\n\n\n\n\n\n\n\n\n\nL\ne\na\ns\nt";
char *bigSmall = (char *)"B\ni\ng\ng\ne\ns\nt\n\n\n\n\n\n\nS\nm\na\nl\nl\ne\ns\nt";
bool debugSquare = false;
bool inTrafficLightFlashMode = false;
int xPosDropBoxLabel = 0;
int xPosDropBox = 0;
bool handPointer = false;
bool drawTissue = false;
bool doingWindowGrab = false;
/* red */
COLORREF layerColorsRed[Max_Shading_Layers_Displayed] = { RGB(255, 255, 255),RGB(220, 220, 255),RGB(165, 165, 255),RGB(105, 105,255),RGB(45, 45, 255),
RGB(0, 0, 240),RGB(0, 0, 180),RGB(0, 0, 120),RGB(0, 0, 60),RGB(30, 30, 60),
RGB(0, 0, 30),RGB(30, 0, 0),RGB(60, 30, 30),RGB(60, 0, 0),RGB(120, 0, 0),
RGB(180, 0, 0),RGB(240, 0, 0),RGB(255, 45, 45),RGB(255, 105, 105),RGB(255, 165, 165) };
/* blue */
COLORREF layerColorsBlue[Max_Shading_Layers_Displayed] = { RGB(255, 255, 255),RGB(255,220, 220),RGB(255,165, 165),RGB(255,105, 105),RGB(255,45, 45),
RGB(240, 0, 0),RGB(180, 0, 0),RGB(120, 0, 0),RGB(60, 0, 0),RGB(60, 30, 30),
RGB(30, 0, 0),RGB(0, 0,30),RGB(30, 30,60),RGB(0, 0,60),RGB(0, 0,120),
RGB(0, 0,180),RGB(0, 0,240),RGB(45, 45,255),RGB(105, 105,255),RGB(165, 165,255) };
/* greyscale*/
COLORREF layerColorsGreyScale[Max_Shading_Layers_Displayed] = { RGB(255, 255, 255),
RGB(240,240, 240),
RGB(235,235, 235),
RGB(225,225, 225),
RGB(215,215, 215),
RGB(205, 205,205),
RGB(195, 195, 195),
RGB(185, 185, 185),
RGB(175, 175, 175),
RGB(165, 165, 165),
RGB(155, 155, 155),
RGB(145, 145,145),
RGB(130, 130,130),
RGB(125, 125,125),
RGB(115, 115,115),
RGB(105, 105,105),
RGB(90, 90,90),
RGB(75, 75,75),
RGB(50, 50,50),
RGB(0, 0,0) };
COLORREF *layerColorsUsed;
CRect targetDrawAreaCRect = { NULL };
unsigned int *growthNodeLayersForDisplay[Max_Shading_Layers_Displayed];
unsigned int *growthNodeLayersForDisplayPtr[Max_Shading_Layers_Displayed];
unsigned short *xyStrings;
class CScreenImage : public CImage
{
public:
BOOL CaptureRect(const CRect& rect);
//BOOL CaptureScreen();
BOOL CaptureWindow(HWND hWnd);
};
CScreenImage *cleanCImage = nullptr;
CImage *drawCImage = nullptr;
bool enterStarted = false;
bool isMove = false;
bool RedFlashMode = false;
bool blackOutClientImageArea = true;
bool windowClientAreaRedraw = false;
bool updateTrackBarValues = false;
HBITMAP trafficLightBitMaps[Traffic_Light_Count];
HBITMAP magButtons[Mag_Button_Count];
HBITMAP magButton;
int magButtonClickCount = 0;
HBITMAP OpenControls;
HBITMAP Camera;
HBITMAP LSWDL;
HBITMAP LSWDS;
HBITMAP LSWDW;
HBITMAP LSWDD;
HBITMAP LSWDGrey;
#define LSWD_Grey 0
#define LSWD_L 1
#define LSWD_S 2
#define LSWD_W 3
#define LSWD_D 4
int autoState = 0;
HBITMAP LBW;
HBITMAP LBD;
HBITMAP LBWD;
HBITMAP autoLayerButton;
HBITMAP WDLTextDisplayBackground;
HBITMAP BWorWB;
HBITMAP overlayColor;
HBITMAP overlayOnOff;
HBITMAP BlackWindow38x25;
HBITMAP helpBubble = nullptr;
HBITMAP helpButtons = nullptr;
HBITMAP helpTrackbars = nullptr;
HBITMAP helpDropdowns = nullptr;
HWND globalhWnd;
HWND layersTrackhWnd = nullptr;
HWND sizeTrackhWnd = nullptr;
HWND whiteTrackhWnd = nullptr;
HWND denseTrackhWnd = nullptr;
//HWND layersDropdownListhWnd = nullptr;
HWND maxMassDropdownListhWnd = nullptr;
HWND stopLayerDropdownListhWnd = nullptr;
HWND mainHelpScreen = nullptr;
HWND mainHelpButtons = nullptr;
HWND mainHelpTrackbars = nullptr;
HWND mainHelpDropdowns = nullptr;
HFONT blackScreenTextFontSmall;
HFONT blackScreenTextFontLarge;
HFONT xtraLargeBlackScreenTextFontLarge;
HFONT blackBoxTextFont;
HFONT sliderNumbersFont;
HFONT dropDownListFont;
HFONT boldLabelFont;
HFONT labelFont;
char WDLTextChar[WDL_Text_Length + 1];
HANDLE mainWorkerThreadWait;
HANDLE *workerThreads;
HANDLE mainWorkerThreadWaitDone;
HANDLE filterThread;
float trackBarPixelCountTicMultiplier = 1;
float trackBarLayersTicMultiplier = 1;
bool killMe = false;
char *staging = (char *)".\\staging.exe";
int threadCount = 0;
///////////////////////////////////////////////////////////////////
bool WDTrackBar = true;
int trafficLightIndex = Green_Light;
UINT_PTR flashTimerID = 0;
RECT holdRect = { NULL };
bool drawGrowthNodes = false;
char *patentText = (char *)"
marginSpiculationCode-ASCII
//////////////////////////////////////////////////////////////////////////
void loadMarginPercentDefine(ShapeDefine *shapeDefine,MarginPercentDefine *marginPercentDefine)
{
typedef struct SpicRunLen
{
int runLen;
int count;
} SpicRunLen;
int inc = 0;
int currentRun = 1;
SpicRunLen* spicRunLen = (SpicRunLen*)malloc(Pixel_Run_Ratio_Count * sizeof(SpicRunLen));
memset(spicRunLen, 0, Pixel_Run_Ratio_Count * sizeof(SpicRunLen));
int direction = Right_Up;
bool lookForEnd = false;
XYPoint* startXYPtr;
XYPoint* endXYPtr;
int xyPointCountNoNegEnd;
if (shapeDefine->shrunkXYPoint != nullptr)
{
startXYPtr = shapeDefine->shrunkXYPoint;
xyPointCountNoNegEnd = shapeDefine->shrunkXYPointCount - 1;
}
else
{
startXYPtr = shapeDefine->xyPoint;
xyPointCountNoNegEnd = shapeDefine->xyPointCount - 1;
}
endXYPtr = startXYPtr + xyPointCountNoNegEnd;
XYPoint* lastXYPoint = startXYPtr - 1;
XYPoint* xyPointPtr = lastXYPoint + 1;
XYPoint* startPixelRun = xyPointPtr;
int pixelRunCount = 0;
while (1)
{
lastXYPoint++;
xyPointPtr++;
if (lastXYPoint >= endXYPtr)
{
lastXYPoint = startXYPtr;
lookForEnd = true;
}
if (xyPointPtr >= endXYPtr)
{
xyPointPtr = startXYPtr;
}
int nextDirection = getDirection(lastXYPoint, xyPointPtr, direction);
if ((direction != nextDirection) || (lookForEnd == true))
{
pixelRunCount++;
int hDistance = distanceBetweenTwoPoints((double)lastXYPoint->xPos, (double)lastXYPoint->yPos,
(double)startPixelRun->xPos, (double)startPixelRun->yPos) + 1; // last should be inclusive. Its' not.
int pixelRatio = ((hDistance * 100) / currentRun);
if ((pixelRatio >= 0) && (pixelRatio < (Pixel_Run_Ratio_Count - 1)))
{
SpicRunLen* spicRunLenPtr = &(spicRunLen[pixelRatio]);
if (lastXYPoint >= startPixelRun)
{
spicRunLenPtr->runLen += ((int)(lastXYPoint - startPixelRun) + 1);
}
else
{
spicRunLenPtr->runLen += ((shapeDefine->xyPointCount - 1) - ((int)(startPixelRun - lastXYPoint) - 1));
}
spicRunLenPtr->count++;
}
else
{
spicRunLen[Pixel_Run_Ratio_Count - 1].count++;
if (lastXYPoint >= startPixelRun)
{
spicRunLen[Pixel_Run_Ratio_Count - 1].runLen += ((int)(lastXYPoint - startPixelRun) + 1);
}
else
{
spicRunLen[Pixel_Run_Ratio_Count - 1].runLen += ((shapeDefine->xyPointCount - 1) - ((int)(startPixelRun - lastXYPoint) - 1));
}
}
if (lookForEnd == true)
{
break;
}
startPixelRun = xyPointPtr;
currentRun = 0;
direction = nextDirection;
}
currentRun++;
}
#define Seventy_Percent_Offset 60
#define Eighty_Percent_Offset 70
#define Ninety_Percent_Offset 80
#define One_Hundred_Percent_Offset 90
/*
#define Eighty_Index 1
#define Ninety_Index 2
#define One_Hundred_Index 3
*/
int* seventyValue = &(marginPercentDefine->value[Seventy_Index]);
*seventyValue = 0;
SpicRunLen* spicRunLenPtr;
spicRunLenPtr = &(spicRunLen[Seventy_Percent_Offset]);
for (inc = Seventy_Percent_Offset; inc < Seventy_Percent_Offset + 10; inc++, spicRunLenPtr++)
{
(*seventyValue) += ((spicRunLenPtr->runLen * 1000) / (shapeDefine->xyPointCount - 1));
}
(*seventyValue) /= 10;
if ((*seventyValue) >= 100)
{
(*seventyValue) = 99;
}
int* eightyValue = &(marginPercentDefine->value[Eighty_Index]);
*eightyValue = 0;
spicRunLenPtr = spicRunLen + Eighty_Percent_Offset;
for (inc = Eighty_Percent_Offset; inc < Eighty_Percent_Offset + 10; inc++, spicRunLenPtr++)
{
*eightyValue += ((spicRunLenPtr->runLen * 1000) / (shapeDefine->xyPointCount - 1));
}
int* ninetyValue = &(marginPercentDefine->value[Ninety_Index]);
*ninetyValue = 0;
spicRunLenPtr = spicRunLen + Ninety_Percent_Offset;
for (inc = Ninety_Percent_Offset; inc < Ninety_Percent_Offset + 10; inc++, spicRunLenPtr++)
{
*ninetyValue += ((spicRunLenPtr->runLen * 1000) / (shapeDefine->xyPointCount - 1));
}
int* oneHundredValue = &(marginPercentDefine->value[One_Hundred_Index]);
*oneHundredValue = 0;
spicRunLenPtr = spicRunLen + One_Hundred_Percent_Offset;
for (inc = One_Hundred_Percent_Offset; inc < One_Hundred_Percent_Offset + 10; inc++, spicRunLenPtr++)
{
*oneHundredValue += ((spicRunLenPtr->runLen * 1000) / (shapeDefine->xyPointCount - 1));
}
free(spicRunLen);
}
/////////////////////////////////////////////////////////////////////////////////////
void loadMarginSpiculationRadiomics(ShapeDefine *shapeDefine)
{
int range = 0; // 10 is one percent
if (spiculationNodes == nullptr)
{
return;
}
SpiculationNode* lastNode;
int radiomicPercentResults[Margin_Percent_Count];
while (1)
{
//shapeDefine->rangeSpiculationRadiomics = nullptr;
int radiomicMatchValue = getMarginCompareSpiculationRange((shapeDefine->marginPercentDefine.value), range, firstNode,-1, &lastNode,1);
if (radiomicMatchValue > -1)
{
shapeDefine->matchRadiomics.radiomicMatchValue = radiomicMatchValue;
return;
}
range+=10; //10 is one percent
if (range > 1000)
{
return;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
int getMarginCompareSpiculationRange(int *value, int range, SpiculationNode* columnNodePtr, int bestRadiomicMatchValue,SpiculationNode **lastNode,
int nodeChildCount)
{
int startRange = *value - range;
int endRange = *value + range;
// range pass Loop
while (1)
{
// send off all siblings within range.
if (columnNodePtr->value < startRange)
{
columnNodePtr = columnNodePtr->sibling;
if (columnNodePtr == nullptr)
{
break;
}
continue;
}
if (columnNodePtr->value > endRange)
{
break;
}
SpiculationNode* localLastNode = nullptr;
int radiomicMatchValue;
if (nodeChildCount != 8)
{
radiomicMatchValue = getMarginCompareSpiculationRange(value + 1, range, columnNodePtr->child, bestRadiomicMatchValue, &localLastNode, nodeChildCount+1);
}
else
{
radiomicMatchValue = getShapeDefineRadiomicColumnDifference(columnNodePtr,value);
}
if ((radiomicMatchValue != -1) && (bestRadiomicMatchValue < radiomicMatchValue))
{
bestRadiomicMatchValue = radiomicMatchValue;
*lastNode = localLastNode;
}
columnNodePtr = columnNodePtr->sibling;
if (columnNodePtr == nullptr)
{
break;
}
}
return(bestRadiomicMatchValue);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int getColumnsSpiculation(SpiculationNode* columnNodePtr, int* valuePtr)
{
int rawSpiculation = 0;
int inc;
for (inc = 0 ; inc < Margin_Percent_Count; inc++,valuePtr--)
{
int distance = abs(columnNodePtr->value - *valuePtr);
// columns individual column distance more weighted then other columns collectively
if (distance > 40) // 40 is 4 percent, one percent for each column.
{
distance += (distance >> 1);
}
rawSpiculation += distance;
columnNodePtr = columnNodePtr->parent;
}
int returnValue = Best_Spiculation - rawSpiculation;
if (returnValue < 0)
{
returnValue = 0;
}
return(returnValue);
}
NormalizedPixelDensity-ASCII
/////////////////////////////////////////////
bool getUsedPixelCountAverageGreyScale(int* imagePixelArray, ShapeDefine* shapeDefine,
CommandData* commandData)
{
int xPos;
int yPos;
int usedPixelCount = 0;
int greyScaleValue = 0;
int width = commandData->shapeWidth;
int height = commandData->shapeHeight;
shapeDefine->width = width;
shapeDefine->height = height;
shapeDefine->xOffsetInCaptureCimage = commandData->xPos;
shapeDefine->yOffsetInCaptureCimage = commandData->yPos;
Mass* mass = commandData->mass;
int screenOverlayCImageXPos = shapeDefine->xOffsetInCaptureCimage - mass->processingPixelSquareOffset;
int screenOverlayCImageYPos = shapeDefine->yOffsetInCaptureCimage - mass->processingPixelSquareOffset;
shapeDefine->rect = { screenOverlayCImageXPos,screenOverlayCImageYPos,
(screenOverlayCImageXPos + shapeDefine->width) - 1,
(screenOverlayCImageYPos + shapeDefine->height) - 1 };
shapeDefine->usedPixels = (XYPoint*)malloc(width * height * sizeof(XYPoint));
if (shapeDefine->usedPixels == nullptr)
{
doAbort((char*)"usedPixels shapeDefine malloc failed inc \n");
}
XYPoint* usedPixelsPtr = shapeDefine->usedPixels;
int xPosOffset = commandData->xPos;
int yPosOffset = commandData->yPos;
int* greyScalePixelsPtr = mass->greyScalePixels;
for (yPos = 0; yPos < height; yPos++)
{
for (xPos = 0; xPos < width; xPos++)
{
int pixelValue = *(imagePixelArray + (xPos + (yPos * width)));
if (pixelValue > -1)
{
usedPixelCount++;
greyScaleValue += *(greyScalePixelsPtr + ((xPos + xPosOffset) + ((yPos + yPosOffset) * screenCaptureWidthAndHeight)));
usedPixelsPtr->xPos = xPos + screenOverlayCImageXPos;
usedPixelsPtr->yPos = yPos + screenOverlayCImageYPos;
usedPixelsPtr++;
}
}
}
#define Check_Percent_Used_Pixel_count ((Min_OIO_Pixel_Count*2)*(Min_OIO_Pixel_Count*2))
if (usedPixelCount <= 0)
{
doAbort((char*)"Used pixel count <= 0. getUsedPixelCountAverageGreyScale");
}
int averageGreyScale = greyScaleValue / usedPixelCount;
int totalPixels = width * height;
if ((totalPixels <= Check_Percent_Used_Pixel_count) && (usedPixelCount < (int)((float)totalPixels * 0.40)))
{
free(shapeDefine->usedPixels);
shapeDefine->usedPixels = nullptr;
shapeDefine->usedPixelCount = 0;
if (shapeDefine->shapeOverlay != nullptr)
{
shapeDefine->shapeOverlay->Destroy();
delete shapeDefine->shapeOverlay;
shapeDefine->shapeOverlay = nullptr;
}
return(false);
}
qsort(shapeDefine->usedPixels, (size_t)usedPixelCount, (size_t) sizeof(XYPoint), compareXYPoint);
shapeDefine->usedPixelCount = usedPixelCount;
shapeDefine->averageGreyScale = averageGreyScale;
if (shapeDefine->averageGreyScale < mass->startPixelDepth)
{
shapeDefine->spiculationRadiomics.normalizedPixelDensity = 0;
}
else
{
if (shapeDefine->averageGreyScale >= (mass->startPixelDepth + mass->pixelDepthLength))
{
shapeDefine->spiculationRadiomics.normalizedPixelDensity = 999;
}
else
{
shapeDefine->spiculationRadiomics.normalizedPixelDensity = ((shapeDefine->averageGreyScale - mass->startPixelDepth) * 1000) / mass->pixelDepthLength;
if (shapeDefine->spiculationRadiomics.normalizedPixelDensity >= 1000)
{
shapeDefine->spiculationRadiomics.normalizedPixelDensity = 999;
}
}
}
/*
// debug
int shapeID = shapeDefine->usedPixelCount + shapeDefine->width + (shapeDefine->height * 2);
// printf("\n** ShapeID %d ave %d norm %d**\n", shapeID, shapeDefine->averageGreyScale, shapeDefine->normalizedPixelDensity);
shapeDefine->xyPoint = commandData->xyPoint;
shapeDefine->xyPointCount = commandData->xyPointCount;
char holdName[101];
sprintf_s(holdName, 100, "shapeID__%d__ave_%d__norm__%d", shapeID, shapeDefine->averageGreyScale, shapeDefine->normalizedPixelDensity);
printf(holdName);
dumpShapeDefine(shapeDefine, holdName, 1, DL_Text_Green, 1, mass);
// end debug
*/
// get distance
shapeDefine->distanceFromClick = getDistanceFromClick(mass->processingPixelSquareMouseXYPos + mass->screenCaptureSquare.xOffset,
mass->processingPixelSquareMouseXYPos + mass->screenCaptureSquare.xOffset, shapeDefine,
commandData->xyPoint, commandData->xyPointCount);
shapeDefine->centerPoint.xPos = (shapeDefine->width / 2) + (shapeDefine->xOffsetInCaptureCimage - mass->processingPixelSquareOffset);
shapeDefine->centerPoint.yPos = (shapeDefine->height / 2) + (shapeDefine->yOffsetInCaptureCimage - mass->processingPixelSquareOffset);
shapeDefine->centerPointDistanceFromClick = distanceBetweenTwoPoints(
(double)(shapeDefine->centerPoint.xPos),
(double)(shapeDefine->centerPoint.yPos),
(double)(mass->processingPixelSquareMouseXYPos),
(double)(mass->processingPixelSquareMouseXYPos));
return(true);
}
centralizedDensityCode-ASCII
// set the main shapes diameter lines.
initRulerPoints(shapeDefine->rulerPoint);
processPixelsManager->setRulerInfo(shapeDefine, mass);
processPixelsManager->getDensistMatchShapeDefineDrawOverlay(shapeDefine, mass, processPixelsManager->greyScaleThreadDefineArray, true);
// }
//selectedShapeDefinesPtrPtr = mass->selectedShapeDefinesPtrPtr;
// for (inc = 0; inc < selectedShapeDefinesCount; inc++, selectedShapeDefinesPtrPtr++)
// {
// ShapeDefine* shapeDefine = *selectedShapeDefinesPtrPtr;
if (shapeDefine->spiculationRadiomics.densityCenterShapeDefine == nullptr)
{
shapeDefine->spiculationRadiomics.density = 1;
shapeDefine->spiculationRadiomics.densityCenter = 1000;
}
else
{
XYPoint centerMassCenterPoint;
getShapeCenterPoint(shapeDefine->spiculationRadiomics.densityCenterShapeDefine, mass, ¢erMassCenterPoint);
XYPoint shapeCenterPoint;
getShapeCenterPoint(shapeDefine, mass, &shapeCenterPoint);
shapeDefine->spiculationRadiomics.densityCenter = (distanceBetweenTwoPoints((double)centerMassCenterPoint.xPos, (double)centerMassCenterPoint.yPos,
(double)shapeCenterPoint.xPos, (double)shapeCenterPoint.yPos) * 1000) /
((shapeDefine->longestDiameter + shapeDefine->diameterHeight) / 2);
//if ((shapeDefine->spiculationRadiomics.densityCenter == 0) && (shapeDefine->usedPixelCount != 1317) && (shapeDefine->usedPixelCount != 1436))
// {
// int i = 0;
// i++;
//}
}
processPixelsManager->getSpiculationFromPixelRunCount(shapeDefine, mass);
}
}
///////////////////////////////////////////////////////////////////
void getDensistMatchShapeDefineDrawOverlay(ShapeDefine* shapeDefine,
Mass *mass, GreyScaleThreadDefine* greyScaleThreadDefinePtr,bool saveCImage)
{
ShapeDefine** holdShapeDefinePtrs = (ShapeDefine**)malloc(mass->massUnusedShapeCount * sizeof(ShapeDefine**));
if (holdShapeDefinePtrs == nullptr)
{
printf("mass->massUnusedShapeCount %d\n", mass->massUnusedShapeCount);
doAbort((char*)"holdShapeDefinePtrs malloc failed");
}
int returnShapeDefineCount = lookForShapesInAShapeInThread(shapeDefine, mass->massUnusedShapeDefines, mass->massUnusedShapeCount,
holdShapeDefinePtrs, mass, greyScaleThreadDefinePtr);
qsort(holdShapeDefinePtrs, (size_t)returnShapeDefineCount,
(size_t)sizeof(ShapeDefine*), compareShapeDefinesRectangleSizeLargeFirstPointers);
// dumpShapeDefineListPtrPtr(returnShapeDefineCount, holdShapeDefinePtrs, mass);
drawAndDisplayActiveMassSetDensity(shapeDefine, holdShapeDefinePtrs, returnShapeDefineCount, mass, saveCImage);
free(holdShapeDefinePtrs);
}
//////////////////////////////////////////////////////////////////////////////////////
int lookForShapesInAShapeInThread(ShapeDefine* marginShapeDefine, ShapeDefine* smallestShapeDefinesFirstPtr,
int shapeDefineCount,ShapeDefine **selectedSubMargins,Mass *mass,
GreyScaleThreadDefine* greyScaleThreadDefinePtr)
{
int inc;
HDC testHDCScreenOverlay = greyScaleThreadDefinePtr->testHDCScreenOverlay;
int* testRgbPtr = greyScaleThreadDefinePtr->testRgbPtr;
//int* testRgbPtr = (int*)marginShapeDefine->shapeOverlay->GetBits();
// HDC testHDCScreenOverlay = marginShapeDefine->shapeOverlay->GetDC();
int returnShapeCount = 0;
for (inc = 0; inc < shapeDefineCount; inc++, smallestShapeDefinesFirstPtr++)
{
if (smallestShapeDefinesFirstPtr->usedPixelCount != 0)
{
if (shapeAInShapeB(smallestShapeDefinesFirstPtr, marginShapeDefine, testHDCScreenOverlay, testRgbPtr, mass,92) == true)
{
*selectedSubMargins = smallestShapeDefinesFirstPtr;
selectedSubMargins++;
returnShapeCount++;
}
}
}
return(returnShapeCount);
}
bool shapeAInShapeB(ShapeDefine* shapeDefineA, ShapeDefine* shapeDefineB, HDC testHDCScreenOverlay,
int* testRgbPtr, Mass* mass, int threadID)
{
RECT intersectRect;
if ((shapeDefineA->width > (shapeDefineB->width + Pixel_Fudge)) && (shapeDefineA->height > (shapeDefineB->height + Pixel_Fudge)))
{
return(false);
}
if (haveIntersect(&(shapeDefineA->rect), &(shapeDefineB->rect), &intersectRect) == true)
{
// rectangle intersects.
// is shapeA in shapeB by pixel count
int intersectPixelCount = havePixelsIntersect(shapeDefineA->usedPixels, shapeDefineB->usedPixels,
shapeDefineA->usedPixelCount, shapeDefineB->usedPixelCount);
if ((shapeDefineB->width < Check_For_Small_Overlap) && (shapeDefineB->height < Check_For_Small_Overlap))
{
// small shape tight border.
int intersectMin = (int)(((float)shapeDefineA->usedPixelCount) * ShapeA_Fudge_Range_Small);
if (intersectPixelCount >= intersectMin)
{
return(true);
}
}
else
{
int intersectMin = (int)(((float)shapeDefineA->usedPixelCount) * ShapeA_Fudge_Range_Large);
// if ((intersectPixelCount >= intersectMin) && (shapeDefineB->usedPixelCount <= maxUsedPixels))
if ((intersectPixelCount >= intersectMin) )
{
return(true);
}
}
if (shapeDefineB->xyPoint == nullptr)
{
return(false);
}
// now check of shape inside shape but not overlap. Bigger shape has a hole in it. little shape in the hole.
if ((shapeDefineA->rect.left == intersectRect.left) &&
(shapeDefineA->rect.top == intersectRect.top) &&
(shapeDefineA->rect.right == intersectRect.right) &&
(shapeDefineA->rect.bottom == intersectRect.bottom))
{
// question now is, is there a shape in a shape but in an empty spot.
//need to draw larger shape, then check if touch it on all four sides. if yes then in it.
drawRectangle(testHDCScreenOverlay, Transparent_Grey_Scale_RGB, 0, 0, mass->processingPixelSquareSize, mass->processingPixelSquareSize);
SelectObject(testHDCScreenOverlay, GetStockObject(DC_PEN));
SelectObject(testHDCScreenOverlay, GetStockObject(DC_BRUSH));
int screenOverlayCImageXPosB = shapeDefineB->xOffsetInCaptureCimage - mass->processingPixelSquareOffset;
int screenOverlayCImageYPosB = shapeDefineB->yOffsetInCaptureCimage - mass->processingPixelSquareOffset;
drawShape(testHDCScreenOverlay, shapeDefineB->xyPoint,
shapeDefineB->xyPointCount, -1,
screenOverlayCImageXPosB, screenOverlayCImageYPosB, 0.0, Used_Grey_Scale_RGB,false);
int centerShapeAXPos = (shapeDefineA->xOffsetInCaptureCimage - mass->processingPixelSquareOffset) +
(shapeDefineA->width >> 1);
int centerShapeAYPos = (shapeDefineA->yOffsetInCaptureCimage - mass->processingPixelSquareOffset) +
(shapeDefineA->height >> 1);
COLORREF pixelColor = *(testRgbPtr + (centerShapeAYPos * mass->pitch) + centerShapeAXPos);
if(pixelColor == Used_Grey_Scale_RGB)
{
// big shape not hollow.
return(false);
}
int xPos;
for (xPos = screenOverlayCImageXPosB; xPos <= centerShapeAXPos; xPos++)
{
pixelColor = *(testRgbPtr + (centerShapeAYPos * mass->pitch) + xPos);
if (pixelColor == Used_Grey_Scale_RGB)
{
break;
}
}
if (xPos > centerShapeAXPos)
{
return(false);
}
for (xPos = screenOverlayCImageXPosB + (shapeDefineB->width - 1); xPos >= centerShapeAXPos; xPos--)
{
if (xPos >= mass->processingPixelSquareSize)
{
continue;
}
pixelColor = *(testRgbPtr + (centerShapeAYPos * mass->pitch) + xPos);
if (pixelColor == Used_Grey_Scale_RGB)
{
break;
}
}
if (xPos < centerShapeAXPos)
{
return(false);
}
int yPos;
for (yPos = screenOverlayCImageYPosB; yPos <= centerShapeAYPos; yPos++)
{
pixelColor = *(testRgbPtr + (yPos * mass->pitch) + centerShapeAXPos);
if (pixelColor == Used_Grey_Scale_RGB)
{
break;
}
}
if (yPos > centerShapeAYPos)
{
return(false);
}
for (yPos = screenOverlayCImageYPosB + (shapeDefineB->height - 1); yPos >= centerShapeAYPos; yPos--)
{
if (yPos >= mass->processingPixelSquareSize)
{
continue;
}
pixelColor = *(testRgbPtr + (yPos * mass->pitch) + centerShapeAXPos);
if (pixelColor == Used_Grey_Scale_RGB)
{
break;
}
}
if (yPos < centerShapeAYPos)
{
return(false);
}
return(true);
}
else
{
#define Min_Intersect_Percent 85
#define Max_Out_Off_Bound_Pixel_Percent 5
if ((shapeDefineA->usedPixelCount < shapeDefineB->usedPixelCount) &&
(intersectPixelCount >= ((shapeDefineA->usedPixelCount * 85) / 100)))
{
if ((shapeDefineA->usedPixelCount - intersectPixelCount) <=
((shapeDefineB->usedPixelCount * Max_Out_Off_Bound_Pixel_Percent) / 100))
{
return(true);
}
}
}
}
return(false);
}
///////////////////////////////////////////////////
bool haveIntersect(RECT* a, RECT* b, RECT* result)
{
// can't use CRect has rounding error with height and width, with small rectangles.
RECT* leftRect;
RECT* rightRect;
RECT* topRect;
RECT* botRect;
if (a->left <= b->left)
{
leftRect = a;
rightRect = b;
}
else
{
leftRect = b;
rightRect = a;
}
// X positions line
if (leftRect->right >= rightRect->left)
{
result->left = rightRect->left;
if (leftRect->right >= rightRect->right)
{
result->right = rightRect->right;
}
else
{
result->right = leftRect->right;
}
if (a->top <= b->top)
{
topRect = a;
botRect = b;
}
else
{
topRect = b;
botRect = a;
}
// X positions line
if (topRect->bottom >= botRect->top)
{
result->top = botRect->top;
if (topRect->bottom >= botRect->bottom)
{
result->bottom = botRect->bottom;
}
else
{
result->bottom = topRect->bottom;
}
return(true);
}
}
return(false);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
int compareShapeDefinesRectangleSizeLargeFirstPointers(const void* arg1, const void* arg2)
{
ShapeDefine* shapeDefine1, * shapeDefine2;
shapeDefine1 = *((ShapeDefine**)arg1);
shapeDefine2 = *((ShapeDefine**)arg2);
if (shapeDefine1->usedPixelCount > shapeDefine2->usedPixelCount)
{
return(-1);
}
if (shapeDefine1->usedPixelCount < shapeDefine2->usedPixelCount)
{
return(1);
}
if (shapeDefine1->xyPointCount > shapeDefine2->xyPointCount)
{
return(-1);
}
if (shapeDefine1->xyPointCount < shapeDefine2->xyPointCount)
{
return(1);
}
return(0);
}
//////////////////////////////////////////////
void drawAndDisplayActiveMassSetDensity(ShapeDefine *marginShapeDefine, ShapeDefine **shapeDefinePtr, int shapeDefinesCount,Mass *mass, bool saveCImage)
{
int bitmapOverlayWH;
int contourDepth = -1;
switch (mass->processingMode)
{
case Mag_Post_Processing:
case Mag_No_Post_Processing:
{
bitmapOverlayWH = (int)((float)(mass->processingPixelSquareSize)
* mass->sizeDecrease);
break;
}
case Post_Processing:
case No_Post_Processing:
{
bitmapOverlayWH = mass->processingPixelSquareSize;
break;
}
}
if (marginShapeDefine->shapeOverlay != nullptr)
{
marginShapeDefine->shapeOverlay->Destroy();
delete marginShapeDefine->shapeOverlay;
}
marginShapeDefine->shapeOverlay = new CImage();
marginShapeDefine->shapeOverlay->Create(bitmapOverlayWH, bitmapOverlayWH, 32);
CImage* overlayCimage = marginShapeDefine->shapeOverlay;
// debug
if (overlayCimage == nullptr)
{
doAbort((char*)"overlayCimage is nullptr");
}
// end debug
displayCImageRgbPtr = (int*)overlayCimage->GetBits();
HDC hdcTmpCImage = overlayCimage->GetDC();
drawRectangle(hdcTmpCImage, Transparent_Grey_Scale_RGB, 0, 0, bitmapOverlayWH, bitmapOverlayWH);
SelectObject(hdcTmpCImage, GetStockObject(DC_PEN));
SelectObject(hdcTmpCImage, GetStockObject(DC_BRUSH));
if (shapeDefinesCount <= 0)
{
overlayCimage->ReleaseDC();
if (saveCImage == true)
{
return;
}
marginShapeDefine->shapeOverlay->Destroy();
delete marginShapeDefine->shapeOverlay;
marginShapeDefine->shapeOverlay = nullptr;
return;
}
marginShapeDefine->spiculationRadiomics.density = drawMassSetDensity(shapeDefinePtr, shapeDefinesCount, mass, displayCImageRgbPtr, hdcTmpCImage, overlayCimage,
&(marginShapeDefine->spiculationRadiomics.densityCenterShapeDefine), &(marginShapeDefine->spiculationRadiomics.pleomorphism));
overlayCimage->ReleaseDC();
if (saveCImage == true)
{
return;
}
marginShapeDefine->shapeOverlay->Destroy();
delete marginShapeDefine->shapeOverlay;
marginShapeDefine->shapeOverlay = nullptr;
return;
}
/////////////////////////////////
int drawMassSetDensity(ShapeDefine** overlayShapeDefinesPtr,int overlayShapeCount,Mass* mass, int* rgbPtr, HDC hdcScreenOverlay,
CImage* cImageOverlay, ShapeDefine **densityCenterShape,int *pleomorphism)
{
//int baseColorIndex = Max_Contour_Layers_Displayed - 1;
int localContourDepth = Max_Contour_Layers_Displayed;
int inc;
int baseXOffset = (*overlayShapeDefinesPtr)->xOffsetInCaptureCimage;
int baseYOffset = (*overlayShapeDefinesPtr)->yOffsetInCaptureCimage;
int xPosOffsetOverlayCimage;
int yPosOffsetOverlayCimage;
int shrunkPixelSquareOffset = 0;
*densityCenterShape = *overlayShapeDefinesPtr;
if (mass->sizeDecrease != 0)
{
shrunkPixelSquareOffset = (int)(((float)(mass->processingPixelSquareOffset)) * mass->sizeDecrease);
}
*pleomorphism = 0;
for (inc = 0; inc < overlayShapeCount; inc++, overlayShapeDefinesPtr++)
{
ShapeDefine* shapeDefine = (*overlayShapeDefinesPtr);
if ((shapeDefine->baseShapeDefineOnly == true) && (inc > 0))
{
continue;
}
int colorIndex;
if (mass->sizeDecrease != 0.0)
{
colorIndex = getDensistPixelColorBeneathTheShapeShrink(rgbPtr, shapeDefine,
(int)(cImageOverlay->GetPitch()) / (int)(sizeof(int)), mass->sizeDecrease, mass->processingPixelSquareOffset);
}
else
{
colorIndex = getDenistUsedPixelColorBeneathTheShape(rgbPtr, shapeDefine,
(int)(cImageOverlay->GetPitch()) / (int)(sizeof(int)));
}
if (colorIndex <= -1)
{
continue;
}
colorIndex = colorIndex - 1;
if (colorIndex < 0)
{
colorIndex = 0;
}
XYPoint* xyPoint = nullptr;
int xyPointCount;
switch (mass->processingMode)
{
case Mag_Post_Processing:
case Mag_No_Post_Processing:
{
int xyPathDataLength = 0;
xyPoint = shapeDefine->shrunkXYPoint;
xyPointCount = shapeDefine->shrunkXYPointCount;
if (xyPoint == nullptr)
{
doAbort((char*)"shrunk xyPoint is nullptr");
}
// has to be shrunk seperate else int rouding screws up offset by pixel sometimes
xPosOffsetOverlayCimage = (int)(((float)(shapeDefine->xOffsetInCaptureCimage) * mass->sizeDecrease));
yPosOffsetOverlayCimage = (int)(((float)(shapeDefine->yOffsetInCaptureCimage) * mass->sizeDecrease));
xPosOffsetOverlayCimage -= shrunkPixelSquareOffset;
yPosOffsetOverlayCimage -= shrunkPixelSquareOffset;
break;
}
case Post_Processing:
case No_Post_Processing:
{
xyPoint = shapeDefine->xyPoint;
xyPointCount = shapeDefine->xyPointCount;
xPosOffsetOverlayCimage = (shapeDefine->xOffsetInCaptureCimage - mass->processingPixelSquareOffset);
yPosOffsetOverlayCimage = (shapeDefine->yOffsetInCaptureCimage - mass->processingPixelSquareOffset);
break;
}
}
if (localContourDepth > colorIndex)
{
localContourDepth = colorIndex;
*densityCenterShape = *overlayShapeDefinesPtr;
}
(*pleomorphism)++;
//printf("UPC %d CI %d\n", (*overlayShapeDefinesPtr)->usedPixelCount, colorIndex);
drawShape(hdcScreenOverlay, xyPoint,
xyPointCount, colorIndex,
xPosOffsetOverlayCimage, yPosOffsetOverlayCimage, 0.0, NULL, false);
/* if (doDebug == true)
{
char holdPath[Max_Path_Len + 2];
WCHAR savePath[MAX_PATH];
size_t outSize;
sprintf_s(holdPath, Max_Path_Len, "C:\\DeepLook\\cCode\\imageTestDumps3\\overlayDisplay_%d_.png", inc);
mbstowcs_s(&outSize, savePath, MAX_LOADSTRING, holdPath, strlen(holdPath));
cImageOverlay->Save(savePath);
int k = 1;
k++;
}
*/
}
// if (dumpShapeDraws == true)
// {
// printf("dUPC %d %d pleo %d %d\n", startUPC, (*holdosdp)->usedPixelCount, *pleomorphism, debugDrawnCount);
// }
return(Max_Contour_Layers_Displayed - localContourDepth);
}
//////////////////////////////////////////////////////////////////////////////////////
void getSelectedMarginSpiculationValues(Mass* mass)
{
// ************** should be turned into multi threads insteand of while loop.
// need to fix the cimage issues.
ShapeDefine** selectedShapeDefinesPtrPtr = mass->selectedShapeDefinesPtrPtr;
//ProcessPixelsQueueElement* processPixelsQueueElement;
// repeat for each new shape found
int selectedShapeDefinesCount = mass->selectedShapeDefineCount;
int inc;
for (inc = 0; inc < selectedShapeDefinesCount; inc++, selectedShapeDefinesPtrPtr++)
{
ShapeDefine* shapeDefine = *selectedShapeDefinesPtrPtr;
debugDrawShape(shapeDefine, mass);
// if (shapeDefine->usedPixelCount == 2359)
// {
// int i = 1;
// i++;
// }
// set the main shapes diameter lines.
initRulerPoints(shapeDefine->rulerPoint);
processPixelsManager->setRulerInfo(shapeDefine, mass);
processPixelsManager->getDensistMatchShapeDefineDrawOverlay(shapeDefine, mass, processPixelsManager->greyScaleThreadDefineArray, true);
// }
//selectedShapeDefinesPtrPtr = mass->selectedShapeDefinesPtrPtr;
// for (inc = 0; inc < selectedShapeDefinesCount; inc++, selectedShapeDefinesPtrPtr++)
// {
// ShapeDefine* shapeDefine = *selectedShapeDefinesPtrPtr;
if (shapeDefine->spiculationRadiomics.densityCenterShapeDefine == nullptr)
{
shapeDefine->spiculationRadiomics.density = 1;
shapeDefine->spiculationRadiomics.densityCenter = 1000;
}
else
{
XYPoint centerMassCenterPoint;
getShapeCenterPoint(shapeDefine->spiculationRadiomics.densityCenterShapeDefine, mass, ¢erMassCenterPoint);
XYPoint shapeCenterPoint;
getShapeCenterPoint(shapeDefine, mass, &shapeCenterPoint);
shapeDefine->spiculationRadiomics.densityCenter = (distanceBetweenTwoPoints((double)centerMassCenterPoint.xPos, (double)centerMassCenterPoint.yPos,
(double)shapeCenterPoint.xPos, (double)shapeCenterPoint.yPos) * 1000) /
((shapeDefine->longestDiameter + shapeDefine->diameterHeight) / 2);
//if ((shapeDefine->spiculationRadiomics.densityCenter == 0) && (shapeDefine->usedPixelCount != 1317) && (shapeDefine->usedPixelCount != 1436))
// {
// int i = 0;
// i++;
//}
}
processPixelsManager->getSpiculationFromPixelRunCount(shapeDefine, mass);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
void getSpiculationFromPixelRunCount(ShapeDefine* shapeDefine, Mass* mass)
{
// debug
if (shapeDefine->matchRadiomics.spiculation != -1)
{
// doAbort((char*)"Spiculation set twice");
}
if (mass->spiculationProfile == nullptr)
{
shapeDefine->matchRadiomics.spiculation = 0;
return;
}
spiculationProfileManager->loadMarginPercentDefine(shapeDefine, &(shapeDefine->marginPercentDefine));
// load relative to the baseSpiculation
shapeDefine->spiculationRadiomics.spiculation = mass->spiculationProfile->getBaseSpiculationColumnDifference(shapeDefine->marginPercentDefine.value, baseSpiculation, Margin_Percent_Count);
shapeDefine->marginPercentDefine.value[Spiculation_Index] = shapeDefine->spiculationRadiomics.spiculation;
shapeDefine->marginPercentDefine.value[Balance_Index] = shapeDefine->spiculationRadiomics.balance;
shapeDefine->marginPercentDefine.value[Density_Center_Index] = shapeDefine->spiculationRadiomics.densityCenter;
shapeDefine->marginPercentDefine.value[Normalized_Pixel_Density] = shapeDefine->spiculationRadiomics.normalizedPixelDensity;
mass->spiculationProfile->loadMarginSpiculationRadiomics(shapeDefine);
return;
}
lesionBalanceCode-ASCII
//////////////////////////////////////////////////////////////////////////////////////////
int getShapeDefineBalance(int *prgb, int usedColor, int widthAndHeight, int pitch,int usePixelCount, int xyOffset, int longestDiameter)
{
int quarterCounts[Quarter_Count * Quarter_Count];
memset(quarterCounts, 0, Quarter_Count * Quarter_Count * sizeof(int));
int halfWidthHeightCimage = widthAndHeight >> 1;
int halfWidthHeight = longestDiameter >> 1;
int oneFourthWH = halfWidthHeight >> 1;
int* rgbPtr = nullptr;
int* quarter;
int inc;
for (inc = 0; inc < Quarter_Count; inc++)
{
quarter = &(quarterCounts[inc * Quarter_Count]);
switch (inc)
{
case 0:
{
rgbPtr = prgb+ ((xyOffset * pitch) + xyOffset);
break;
}
case 1:
{
rgbPtr = prgb + ((xyOffset * pitch) + halfWidthHeightCimage);
break;
}
case 2:
{
rgbPtr = prgb + ((halfWidthHeightCimage * pitch) + xyOffset);
break;
}
case 3:
{
rgbPtr = prgb + (halfWidthHeightCimage * pitch) + halfWidthHeightCimage;
break;
}
}
int xPos;
int yPos;
for (yPos = 0; yPos < oneFourthWH; yPos++)
{
int* pixelRunLenPtr = (rgbPtr + (yPos * pitch));
for (xPos = 0; xPos < oneFourthWH; xPos++, pixelRunLenPtr++)
{
if (*pixelRunLenPtr == usedColor)
{
quarter[0]++;
}
}
}
for (yPos = 0; yPos < oneFourthWH; yPos++)
{
int* pixelRunLenPtr = (rgbPtr + ((yPos * pitch) + oneFourthWH));
for (xPos = 0; xPos < oneFourthWH; xPos++, pixelRunLenPtr++)
{
if (*pixelRunLenPtr == usedColor)
{
quarter[1]++;
}
}
}
for (yPos = oneFourthWH; yPos < halfWidthHeight; yPos++)
{
int* pixelRunLenPtr = (rgbPtr + (yPos * pitch));
for (xPos = 0; xPos < oneFourthWH; xPos++, pixelRunLenPtr++)
{
if (*pixelRunLenPtr == usedColor)
{
quarter[2]++;
}
}
}
for (yPos = oneFourthWH; yPos < halfWidthHeight; yPos++)
{
int* pixelRunLenPtr = (rgbPtr + ((yPos * pitch) + oneFourthWH));
for (xPos = 0; xPos < oneFourthWH; xPos++, pixelRunLenPtr++)
{
if (*pixelRunLenPtr == usedColor)
{
quarter[3]++;
}
}
}
}
// get one fourth difference count;
int differenceCount = 0;
int* qUpperLeft = quarterCounts ;
int* qUpperRight = qUpperLeft + Quarter_Count;
int* qLowerLeft = qUpperRight + Quarter_Count;
int* qLowerRight = qLowerLeft + Quarter_Count;
differenceCount += getDiffLeftToRight(qUpperLeft, qUpperRight);
differenceCount += getDiffTopToBot(qUpperLeft, qLowerLeft);
differenceCount += getDiffDiag(qUpperLeft, qLowerRight);
differenceCount += getDiffDiag(qUpperRight, qLowerLeft);
differenceCount += getDiffTopToBot(qUpperRight, qLowerRight);
differenceCount += getDiffLeftToRight(qLowerLeft,qLowerRight );
int balance = 1000 - ((differenceCount * 1000) / usePixelCount);
if (balance >= 1000)
{
balance = 999;
}
//if (balance <= 0)
// {
// balance = 1;
// }
return(balance);
}
#define Quarter_Count 4
//////////////////////////////////////////////////
int getDiffLeftToRight(int* left, int* right)
{
int differenceCount = 0;
differenceCount += abs(*left - *(right + 1));
differenceCount += abs(*(left + 1) - *right);
differenceCount += abs(*(left + 2) - *(right + 3));
differenceCount += abs(*(left + 3) - *(right + 2));
return(differenceCount);
}
//////////////////////////////////////////////////
int getDiffTopToBot(int* top, int* bot)
{
int differenceCount = 0;
differenceCount += abs(*top - *(bot + 2));
differenceCount += abs(*(top + 1) - *(bot + 3));
differenceCount += abs(*(top + 2) - *bot);
differenceCount += abs(*(top + 3) - *(bot + 1));
return(differenceCount);
}
//////////////////////////////////////////////////
int getDiffDiag(int* topLeft, int* botRight)
{
int differenceCount = 0;
differenceCount += abs(*topLeft - *(botRight + 3));
differenceCount += abs(*(topLeft + 1) - *(botRight + 2));
differenceCount += abs(*(topLeft + 2) - *(botRight + 1));
differenceCount += abs(*(topLeft + 3) - *botRight);
return(differenceCount);
}
additionalDensitySupportcode-ASCII
//////////////////////////////////////////////////////////
COLORREF getDensistPixelColorBeneathTheShapeShrink(int* rgbPtr, ShapeDefine* shapeDefine, int pitch, float sizeDecrease, int processingPixelSquareOffset)
{
XYPoint* usedPixelsPtr = shapeDefine->usedPixels;
int usedPixelCount = shapeDefine->usedPixelCount;
COLORREF usedColors[Max_Contour_Layers_Displayed];
int colorCount[Max_Contour_Layers_Displayed];
int usedColorsCount = 0;
memset(usedColors, -1, sizeof(COLORREF) * Max_Contour_Layers_Displayed);
memset(colorCount, 0, sizeof(int) * Max_Contour_Layers_Displayed);
int inc;
int inc2;
int maxYpos = abs(pitch);
int xPosCImageOffset = shapeDefine->xOffsetInCaptureCimage - processingPixelSquareOffset;
int yPosCImageOffset = shapeDefine->yOffsetInCaptureCimage - processingPixelSquareOffset;
int xShrunkOffset = (int)((float)xPosCImageOffset * sizeDecrease);
int yShrunkOffset = (int)((float)yPosCImageOffset * sizeDecrease);
for (inc = 0; inc < usedPixelCount; inc++, usedPixelsPtr++)
{
int xPos = (int)(((float)usedPixelsPtr->xPos - xPosCImageOffset) * sizeDecrease) + xShrunkOffset;
int yPos = (int)(((float)usedPixelsPtr->yPos - yPosCImageOffset) * sizeDecrease) + yShrunkOffset;
if (yPos >= maxYpos)
{
yPos--;
}
COLORREF pixelColor = *(rgbPtr + (pitch * yPos ) + xPos);
// debug
// {
// printf("inc %d xPos %d yPos %d color %x\n",inc,xPos,yPos,pixelColor);
//}
// end debug
if (pixelColor == Transparent_Grey_Scale_RGB)
{
continue;
}
for (inc2 = 0; inc2 < usedColorsCount; inc2++)
{
if (usedColors[inc2] == pixelColor)
{
colorCount[inc2]++;
break;
}
}
if (inc2 >= usedColorsCount)
{
// if here not found.
usedColors[usedColorsCount] = pixelColor;
colorCount[usedColorsCount] = 1;
usedColorsCount++;
}
}
int mustHave = (usedPixelCount * 98) / 100;
if (usedColorsCount > 0)
{
for (inc = 0; inc < usedColorsCount; inc++)
{
if (colorCount[inc] >= mustHave)
{
return(getLayerColor(usedColors[inc], layerColorsUsed));
}
}
return(-1);
}
return(Max_Contour_Layers_Displayed);
}
【0224】
結論
【0225】
以上、先に述べた目的を満たすシステム、装置及び方法を説明した。図示された実施形態は本発明の単なる例示であり、ここに示されたものに対する変更を組み込んだ他の実施形態も本発明の範囲内にあることが理解されよう。
【国際調査報告】