ソースコード

% ------------------------------------------------------

% 120224

% AlignStack作成

% ------------------------------------------------------

% test_FRETImageProcess → FRETImageProcess2

% Showを廃止、代わりにAdjustを作成

% Movieの画像補正の部分をAdjustにする

% SortNLSNESCAAXでNESかCAAXかを判定する基準のSDを引数で指定させる

% 核内intensityの微分のSDをNES判定材料に加える

% MovieFromTiff作成

% RatioImageFromTiff作成

% ------------------------------------------------------

% FRETImageProcess → test_FRETImageProcess

% parforに対応させる

% parfor内でtiffオブジェクトを読み込むとバグが起こるのでReadTiffFileでtiffオブジェクトではなく画像とタグとして読み込む

% それにあわせてGetImageとGetTimeofImageを変更、RegionForOutputのImageLengthとImageWidthの読み込み方を変更

% 画像表示(自動補正)

% レシオ画像作成

% ムービー

% コメント化された旧アルゴリズムを削除

% -------------------------------------------------------

classdef FRETImageProcess2

methods (Static)

% イメージング情報が記述されたndファイルを読み込んでimaging_info構造体に格納

function imaging_info = ReadNDFile(directory, filename)

% ファイルアドレスをimaging_data構造体に格納

imaging_info.directory = directory;

imaging_info.filename = filename;

% ndファイルを読み込んで文字列リストとして格納

fid = fopen([directory, '\', filename, '.nd']);

cellarray = textscan(fid, '%s', 'delimiter', ','); % セル配列が返る

nd = cellarray{1}; % 行列に格納

fclose(fid);

% 読み込んだ文字列リストからimaging_info構造体に格納

for i = 1 : length(nd)

if strcmp(nd(i), '"StartTime1"') % start day and time (秒単位 seconds)

date = nd{i + 1}; % nd(i + 1)とするとセル配列が入る

imaging_info.start_time = datenum(date,'yyyymmdd HH:MM:SS') * 86400; % 文字列から秒単位の数値に変換

elseif strcmp(nd(i), '"DoTimelapse"') % Timelapse on or off

imaging_info.do_timelapse = nd{i + 1};

elseif strcmp(nd(i), '"NTimePoints"') % number of timepoints

imaging_info.timepoints = str2double(nd(i + 1));

elseif strcmp(nd(i), '"NStagePositions"') % number of positions

imaging_info.positions = str2double(nd(i + 1));

elseif strcmp(nd(i), '"NWavelengths"') % number of wavelengths

imaging_info.wavelengths = str2double(nd(i + 1));

elseif strcmp(nd{i}(2:length(nd{i}) -2) , 'WaveName') % 「" "」と数字を除く("WaveName1" → WaveName)

num = str2double(nd{i}(length(nd{i}) -1)); % nd(i)とすると文字列ではなくセル配列が返る

imaging_info.wavename{num} = nd{i + 1}(2:length(nd{i + 1}) -1); % wavenameはセル配列

end

end

end % ReadNDFile

% Tiffファイルの読み込み

function [Image_array Time_array] = ReadTiffFile(imaging_info) % 引数はReadNDFile関数の返り値の構造体

Image_array = cell(imaging_info.wavelengths, imaging_info.positions, imaging_info.timepoints);

Time_array = zeros(imaging_info.wavelengths, imaging_info.positions, imaging_info.timepoints);

warning off all; % 警告メッセージを非表示にする

for i = 1 : imaging_info.wavelengths

for j = 1 : imaging_info.positions

for k = 1 : imaging_info.timepoints

% Tiffファイルのパスを設定

if strcmp(imaging_info.do_timelapse, 'FALSE')

path = [imaging_info.directory, '\', imaging_info.filename, '_w', int2str(i), imaging_info.wavename{i}, '_s', int2str(j), '.TIF'];

else

path = [imaging_info.directory, '\', imaging_info.filename, '_w', int2str(i), imaging_info.wavename{i}, '_s', int2str(j), '_t', int2str(k), '.TIF'];

end

% Tiffオブジェクト(読み込みモード)として読み込み

tiff_temp = Tiff(path, 'r');

% readで画像を読み込み

Image_array{i,j,k} = read(tiff_temp);

% 撮影時刻を読み込み

DateTime = tiff_temp.getTag('DateTime');

% 文字列から秒単位の数値に変換

Time_array(i,j,k) = datenum(DateTime, 'yyyy:mm:dd HH:MM:SS') * 86400;

end

end

end

warning on all; % 警告メッセージ非表示の解除

end % ReadTiffFile

% 読み込んだTiffオブジェクトから指定した画像を取得

function Image = GetImage(Imaging_info, Tiff_array, timepoint, position, wavename)

% wavenameが何番目のwavelengthかを調べる

for i = 1:Imaging_info.wavelengths

if strcmp(Imaging_info.wavename{i} , wavename)

waveID = i;

break

end

if i == Imaging_info.wavelengths

fprintf('指定したwavenameは存在しません \n')

waveID = 0;

end

end

Image = Tiff_array{waveID, position, timepoint};

end % GetImage

% 読み込んだTiffオブジェクトから指定した画像の撮影時刻を取得

function TimeOfImage = GetTimeOfImage(Imaging_info, Time_array, timepoint, position, wavename)

% wavenameが何番目のwavelengthかを調べる

for i = 1:Imaging_info.wavelengths

if strcmp(Imaging_info.wavename{i} , wavename)

waveID = i;

break

end

if i == Imaging_info.wavelengths

fprintf('指定したwavenameは存在しません \n')

waveID = 0;

end

end

% 撮影時刻を取得

TimeOfImage = Time_array(waveID, position, timepoint);

end % GetTimeOfImage

% 画像をintensityが最大255,最小0になるように自動補正

function AdjustedImage = Adjust(Image)

% doubleに型変換

Image = double(Image);

% ratio画像(カラー)の場合、各色の画像を並べる

if size(Image,3) == 3

ref_image = [Image(:,:,1), Image(:,:,2), Image(:,:,3)];

else

ref_image = Image;

end

width = size(ref_image,2);

height = size(ref_image,1);

% intensity histogram作成

mi = max(max(ref_image));

dist = zeros(mi+1,2);

dist(:,1) = 0:mi;

for y = 1:size(ref_image,1)

for x = 1:size(ref_image,2)

dist(ref_image(y,x)+1,2) = dist(ref_image(y,x)+1,2) + 1;

end

end

% intensity windowをmin_intとmax_intをintensity histogramの上下0.3%になるように設定

min_adjust = 0;

n = 0;

while n < 0.003 * width * height

min_adjust = min_adjust + 1;

n = sum(dist(1:min_adjust+1, 2));

end

rows = size(dist,1);

max_adjust = rows - 1;

m = 0;

while m < 0.003 * width * height

max_adjust = max_adjust - 1;

m = sum(dist(max_adjust+1:rows, 2));

end

% intensityを最大255,最小0になるように補正

AdjustedImage = uint8((Image - min_adjust) / (max_adjust - min_adjust) * 255);

end % Adjust

% アニメーション表示、ムービーフレーム作成(フレームはmovie2avi関数でAVIファイルに変換することができる)

function Frames = Movie(ImageCellArray, interval)

% モノクロまたはカラーの画像のセル配列ImageCellArrayをアニメーション表示

figure;

for i = 1 : length(ImageCellArray)

% 1枚の画像を取得、doubleに型変換

Image = double(ImageCellArray{i});

% 画像を自動補正

adjusted_image = FRETImageProcess2.Adjust(Image);

% 描画

imshow(adjusted_image);

% 画像更新

drawnow;

% ムービーフレームとして格納(フレームにすると上下が反転するためflipdimで修正)

Frames(i) = im2frame(flipdim(adjusted_image, 1), colormap);

% インターバル

pause(interval);

end

% フレームから再生

% movie(Frames);

% aviファイル作成

% movie2avi(Frames, filename, 'fps', 10);

end % Movie

% アニメーション表示、ムービーフレーム作成(フレームはmovie2avi関数でAVIファイルに変換することができる)

% ReadTiffFileで読み込んだ{wavelength, position, timepoint}の配列を引数とする

function Frames = MovieFromTiff(Imaging_info, TiffArray, Position, Wavename, interval)

figure;

% wavenameが何番目のwavelengthかを調べる

for i = 1:Imaging_info.wavelengths

if strcmp(Imaging_info.wavename{i} , Wavename)

waveID = i;

break

end

if i == Imaging_info.wavelengths

fprintf('指定したwavenameは存在しません \n')

waveID = 0;

end

end

for timepoint = 1 : size(TiffArray, 3)

% 1枚の画像を取得、doubleに型変換

Image = double(TiffArray{waveID, Position, timepoint});

% 画像を自動補正

adjusted_image = FRETImageProcess2.Adjust(Image);

% 描画

imshow(adjusted_image);

% 画像更新

drawnow;

% ムービーフレームとして格納(フレームにすると上下が反転するためflipdimで修正)

Frames(timepoint) = im2frame(flipdim(adjusted_image, 1), colormap);

% インターバル

pause(interval);

end

% フレームから再生

% movie(Frames);

% aviファイル作成

% movie2avi(Frames, filename, 'fps', 10);

end % MovieWPT

% ratio画像作成(timepoint数分)、ムービー表示

function ResultImage_array = RatioImage(FRETImages, CFPImages, min_ratio, max_ratio)

% 引数のFRETImages,CFPImagesは(height,width)の2次元配列または(height,width,timepoints)の3次元配列

% 戻り値はカラー画像行列のセル配列

% 画像サイズとtimepoint数を取得

height = size(FRETImages,1);

width = size(FRETImages,2);

timepoints = size(FRETImages, 3);

% 戻り値宣言

ResultImage_array = cell(1,timepoints);

% 各timepointにおけるRatio画像作成

for t = 1:timepoints

% 各timepointにおける画像を取得

image_FRET = FRETImages(:,:,t);

image_CFP = CFPImages(:,:,t);

% ratioを計算

ratio = double(image_FRET) ./ double(image_CFP);

% 0で割ってNaNやInfになったものを0にする

ratio(isnan(ratio)) = 0;

ratio(isinf(ratio)) = 0;

% 最小0、最大510になるように補正

ratio = (ratio - min_ratio) / (max_ratio - min_ratio) * 510;

color_ratio = zeros(height, width, 3);

% 1~255 : 青低下、緑上昇 256~510 : 緑低下、赤上昇

color_ratio(:,:,1) = uint8(ratio - 255);

color_ratio(:,:,2) = uint8(-abs(ratio - 255) + 255);

color_ratio(:,:,3) = uint8(255 - ratio);

% intensityによって補正

ref_image = zeros(height, width, 3);

ref_image(:,:,1) = double(image_FRET);

ref_image(:,:,2) = double(image_FRET);

ref_image(:,:,3) = double(image_FRET);

max_int = max(max(max(ref_image)));

min_int = min(min(min(ref_image)));

adjusted_color_ratio = double(color_ratio) .* ((ref_image - min_int) / (max_int - min_int));

ResultImage_array{t} = uint8(adjusted_color_ratio);

end

% ムービー表示

FRETImageProcess2.Movie(ResultImage_array, 0.02);

end % RatioImage

% backgroundを引いてratio画像作成、ムービー表示

% ReadTiffFileで読み込んだ{wavelength, position, timepoint}の配列を引数とする

function ResultImage_array = RatioImageFromTiff(Imaging_info, TiffArray, position, min_ratio, max_ratio)

% FRETとCFPが何番目のwavelengthかを調べる

waveID_FRET = 0;

waveID_CFP = 0;

for i = 1:Imaging_info.wavelengths

if strcmp(Imaging_info.wavename{i} , 'FRET')

waveID_FRET = i;

end

if strcmp(Imaging_info.wavename{i} , 'CFP')

waveID_CFP = i;

end

if i == Imaging_info.wavelengths

if waveID_FRET == 0

fprintf('FRETのwavenameが存在しません \n')

return

end

if waveID_CFP == 0

fprintf('CFPのwavenameが存在しません \n')

return

end

end

end

width = size(TiffArray{1,1,1}, 2);

height = size(TiffArray{1,1,1}, 1);

% FRETとCFPの3次元画像行列(height,width,timepoint)を作成

FRETImages = uint16(zeros(height, width, Imaging_info.timepoints));

CFPImages = uint16(zeros(height, width, Imaging_info.timepoints));

for t = 1:Imaging_info.timepoints

FRETImages(:,:,t) = TiffArray{waveID_FRET, position, t};

CFPImages(:,:,t) = TiffArray{waveID_CFP, position, t};

end

% backgroundを引く

FRET_background = FRETImageProcess2.FigureBackground(FRETImages(:,:,1));

CFP_background = FRETImageProcess2.FigureBackground(CFPImages(:,:,1));

for t = 1:Imaging_info.timepoints

FRETImages(:,:,t) = FRETImages(:,:,t) - FRET_background;

CFPImages(:,:,t) = CFPImages(:,:,t) - CFP_background;

end

% RatioImageを呼び出してレシオ画像作成

ResultImage_array = FRETImageProcess2.RatioImage(FRETImages, CFPImages, min_ratio, max_ratio);

end % RatioImageWPT

% Intensityヒストグラム作成

function Distribution = IntensityHistogram(Image) % Image : Tiff_array{i,j,k} or read(Tiff_array{i,j,k})

if strcmp(class(Image), 'Tiff')

img = read(Image);

else

img = round(Image);

end

m = max(max(img));

dist = zeros(m+1,2);

dist(:,1) = 0:m;

for i = 1:size(img,1)

for j = 1:size(img,2)

dist(img(i,j)+1,2) = dist(img(i,j)+1,2) + 1;

end

end

dist(:,1) = 0:m;

figure, bar(dist(:,2)) % ヒストグラム描画(新規figure)

Distribution = dist;

end % IntensityHistogram

% Background intensityを求める

function Background_intensity = FigureBackground(Image)

% 8x8ピクセルの領域を4ピクセルずつ動かしていき、それぞれの領域における平均輝度のうち最小のものをbackgroundとする

if strcmp(class(Image), 'Tiff')

img = read(Image);

else

img = round(Image);

end

radius = (size(img,1) + size(img,2)) / 4;

mean_array = zeros(length(1:4:size(img,1)-8) * length(1:4:size(img,2)-8) , 3);

count = 1;

for y = 1:4:size(img,1)-8

for x = 1:4:size(img,2)-8

if (((x+3 - radius)^2 + (y+3 - radius)^2) < radius^2) % 四隅は暗いので除く

region = img(y:y+7, x:x+7);

mean_array(count,1) = x;

mean_array(count,2) = y;

mean_array(count,3) = round(mean(mean(region)));

count = count + 1;

end

end

end

% mean_arrayの余分な行を削除

mean_array = mean_array(1:count-1, 1:3);

% mean_arrayの最小値をbackgroundとする

Background_intensity = min(mean_array(:,3));

end

% 画像の位置が時間がたつにつれてずれていくのを修正

% ImageStackは{wavelength,position,timepoint}のセル配列

function AlignedStack = AlignStack(ImageStack)

width = size(ImageStack{1,1,1}, 2);

height = size(ImageStack{1,1,1}, 1);

num_wavelengths = size(ImageStack, 1);

num_positions = size(ImageStack, 2);

num_timepoints = size(ImageStack, 3);

ImageStack2 = ImageStack;

for p = 1 : num_positions

% 各background計算

background = zeros(num_wavelengths, num_positions);

for w = 1:num_wavelengths

background(w,p) = FRETImageProcess2.FigureBackground(ImageStack{w,p,1});

end

% 各timepointについてずれを修正

adjust_x = 0;

adjust_y = 0;

t = 2;

while t <= num_timepoints

subtract = zeros(5,5);

% timepoint=1の画像とtimepoint=tの画像を比較

% timepoint = 1, t の画像を縦横に-2~2ピクセルずらしながら差分を計算

for y = -2:2

for x = -2:2

% adjust_x,y はひとつ前のtについての補正値

cx = adjust_x + x;

cy = adjust_y + y;

subtract(y+3,x+3) = sum(sum(ImageStack{1,p,1}(max(1,1+cy):min(height,height+cy), max(1,1+cx):min(width,width+cx))...

- ImageStack{1,p,t}(max(1,1-cy):min(height,height-cy), max(1,1-cx):min(width,width-cx))));

end

end

% 差分が最小になるようなずらし幅x,yを取得

min_of_subtract = subtract * 0;

min_of_subtract(subtract == min(min(subtract))) = 1;

for x = 1:5

if sum(min_of_subtract(:,x) == 1) > 0

break;

end

end

for y = 1:5

if sum(min_of_subtract(y,:) == 1) > 0

break;

end

end

% 1~5 を -2~2 に補正

x = x - 3;

y = y - 3;

% 合計のadjust_x,y( = position1と合わせるためのadjustx,y)

adjust_x = adjust_x + x;

adjust_y = adjust_y + y;

% x,yが-2または2であればさらにずらして調べる

if (x == -2) || (x == 2) || (y == -2) || (y == 2)

continue;

end

% timepoint = tの画像をずらす

for w = 1:num_wavelengths

ImageStack2{w,p,t} = ImageStack2{w,p,t} * 0 + background(w,p);

ImageStack2{w,p,t}(max(1,1+adjust_y):min(height,height+adjust_y), max(1,1+adjust_x):min(width,width+adjust_x))...

= ImageStack{w,p,t}(max(1,1-adjust_y):min(height,height-adjust_y), max(1,1-adjust_x):min(width,width-adjust_x));

end

t = t + 1;

end

end

AlignedStack = ImageStack2;

end % AlignStack

% watershedアルゴリズムによる核染色画像のsegmentation

function SegmentationMatrix = Segmentation(NucleusImage) % Image : Tiff_array{i,j,k} or read(Tiff_array{i,j,k})

if strcmp(class(NucleusImage), 'Tiff')

img = read(NucleusImage);

else

img = round(NucleusImage);

end

% 前処理として細かくopening-by-reconstruction

se = strel('disk', 2);

le = imerode(img,se);

img = imreconstruct(le,img);

% intensityを平らにする

for i = 1 : 3

rm = imregionalmax(img);

rm = img .* uint16(rm);

rmlow = rm * 0.90; % 局所的最大値の少し下を取得

robr = imreconstruct(rmlow,img);

fgmr = imregionalmax(robr);

cc = bwconncomp(fgmr); % 領域分割

for j = 1 : cc.NumObjects

img(cc.PixelIdxList{1,j}) = mean(img(cc.PixelIdxList{1,j})); % 各領域内の値を平均化

end

end

% figure,imshow(img * 16);

fgm = imregionalmax(img);

% figure,imshow(fgm);

% watershedで領域分割

L_dist = -bwdist(~fgm);

L_dist(~fgm) = -Inf;

L_seg = watershed(L_dist);

% figure,imshow(label2rgb(L_seg,'jet'));

SegmentationMatrix = L_seg;

end

% segmentationした核の位置情報をもとに、核内と核周囲の平均intensityを計算

function intensity_array = CheckIntensityAroundNucleus(FRETImage, SegmentationMatrix)

if strcmp(class(FRETImage), 'Tiff')

img = read(FRETImage);

else

img = uint16(round(FRETImage));

end

se = strel('disk', 1); % imdilate(膨張処理)用

count = 3; % 何ピクセル外側まで調べるか

dilated_nucleusregion = cell(1,count+1);

external_nucleusregion = cell(1,count);

external_image = cell(1,count);

external_intensity = cell(1,count);

result_array = zeros(max(max(SegmentationMatrix)), count+1);

for i = 2:max(max(SegmentationMatrix))

% 核の領域を取得

nucleusregion = uint16(SegmentationMatrix == i);

nucleusregion = imdilate(nucleusregion, strel('disk',1)); % 境界部が含まれないので拡張

% 核内全体の平均intensityを求める

nucleus_image = img .* nucleusregion;

nucleus_intensity = sum(sum(nucleus_image)) / sum(sum(nucleusregion));

result_array(i, 2) = nucleus_intensity;

% 核の縁(0ピクセル外側)の平均intensityを求める

eroded_nucleusregion = imerode(nucleusregion, se);

border_nucleusregion = uint16(eroded_nucleusregion ~= nucleusregion);

border_image = img .* border_nucleusregion;

border_intensity = sum(sum(border_image)) / sum(sum(border_nucleusregion));

result_array(i, 3) = border_intensity;

% 核の外側の平均intensityを求める

dilated_nucleusregion{1} = nucleusregion;

for j = 1:count

dilated_nucleusregion{j+1} = imdilate(dilated_nucleusregion{j},se); % 1ピクセル分膨張処理

external_nucleusregion{j} = uint16(dilated_nucleusregion{j+1}~=dilated_nucleusregion{j}); % 外側の領域だけ取り出し

external_image{j} = img .* external_nucleusregion{j};

external_intensity{j} = sum(sum(external_image{j})) / sum(sum(external_nucleusregion{j}));

result_array(i, j+3) = external_intensity{j};

end

end

intensity_array = result_array;

end

% 領域拡張法 : seedbinaryimage(核)の2倍の直径程度に膨張処理した領域内での領域拡張

% 拡張条件はcriteiaの値(文字列)により異なる。 'NLS', 'NES', 'CAAX'のいずれか

% SeedBinaryImageは1細胞の核の領域のみであることを前提とする

% メモ:imresizeで画像サイズ変更

function GrownBinaryImage = RegionGrowing(image, SeedBinaryImage)

if strcmp(class(image), 'Tiff')

img = read(image);

else

img = uint16(round(image));

end

width = size(img, 2);

height = size(img, 1);

GrownBinaryImage = SeedBinaryImage; % 拡張したイメージ

FinishedBinaryImage = logical(SeedBinaryImage * 0); % region growingを終えたseed point(次のseed pointにはならない)

NextSeedBinaryImage = (GrownBinaryImage ~= FinishedBinaryImage);

% 核(SeedBinaryImage)をひとまわり大きくした領域を求める。GrownBinaryImageはこの領域内におさめる

numberofpoints = sum(sum(SeedBinaryImage));

strel_radius = round(sqrt(numberofpoints)); % 面積がnumberofpointsの円の半径

dilated_region = imdilate(SeedBinaryImage, strel('disk',strel_radius));

% criteria = 'CAAX'のとき用にSeedBinaryImage領域内の平均intensityを計算

%mean_seed_intensity = sum(img(SeedBinaryImage)) / sum(sum(SeedBinaryImage));

% 領域拡張ループ

while sum(sum(NextSeedBinaryImage)) > 0

% seed pointの座標を取得

seed_list = zeros(sum(sum(NextSeedBinaryImage)), 2); % 行数 = seed pointの数、列 = x,y

count = 0;

for y = 1:height

for x = 1:width

if NextSeedBinaryImage(y,x) == 1

count = count + 1;

seed_list(count, 1) = x;

seed_list(count, 2) = y;

end

end

end

% 各seed pointについて領域拡張

for i = 1:count

seed_point_x = seed_list(i,1);

seed_point_y = seed_list(i,2);

seed_intensity = img(seed_point_y, seed_point_x);

% seed pointの周囲8ピクセルを調べる

for y = 1:3

for x =1:3

grow_point_x = seed_point_x + x - 2;

grow_point_y = seed_point_y + y - 2;

if (grow_point_x < 1) || (grow_point_x > width) || (grow_point_y < 1) || (grow_point_y > height)

continue

end

% 領域拡張条件

if (img(grow_point_y, grow_point_x) > seed_intensity * 0.9)

GrownBinaryImage(grow_point_y, grow_point_x) = 1;

end

end

end

% GrownBinaryImageはdilated_region内におさめる

GrownBinaryImage = logical(GrownBinaryImage .* dilated_region);

FinishedBinaryImage(seed_point_y, seed_point_x) = 1;

end

NextSeedBinaryImage = (GrownBinaryImage ~= FinishedBinaryImage);

end

end

% 領域拡張法によるNLS,NES,CAAXの判別

function SortArray = SortNLSNESCAAX(FRETimage, SegmentationMatrix, SD_NES, SD_CAAX)

if strcmp(class(FRETimage), 'Tiff')

img = read(FRETimage);

else

img = uint16(round(FRETimage));

end

cells = zeros(max(max(SegmentationMatrix)) , 1); % 各細胞がNLS,NES,CAAXのどれであるかを格納する行列

nucleus_size_array = zeros(max(max(SegmentationMatrix)) , 1); % 各細胞の核のサイズを格納

nucleus_intensity_array = zeros(max(max(SegmentationMatrix)) , 1); % 各細胞の核の平均intensityを格納

% sd_array = zeros(max(max(SegmentationMatrix)) , 1); j = 1;

intensity_array = FRETImageProcess2.CheckIntensityAroundNucleus(FRETimage, SegmentationMatrix);

% prewittフィルタでエッジ(微分)抽出

horiz = filter2([-1,0,1;-1,0,1;-1,0,1],img);

vert = filter2([-1,-1,-1;0,0,0;1,1,1],img);

differential_img = (horiz .* horiz + vert .* vert) .^ 0.5;

for i = 2:length(cells) % i = 1は背景

nucleus_region = SegmentationMatrix == i;

nucleus_region = imdilate(nucleus_region, strel('disk',1)); % 境界部が含まれないので拡張

mean_nucleus_intensity = mean(img(nucleus_region));

nucleus_size_array(i) = sum(sum(nucleus_region));

nucleus_intensity_array(i) = mean_nucleus_intensity;

% NLSかどうかの判定(周辺数ピクセルを調べる)

r0 = intensity_array(i,3) / intensity_array(i,2); % 核の0ピクセル外側 / 核内全体

r1 = intensity_array(i,4) / intensity_array(i,3); % 核の1ピクセル外側 / 核の0ピクセル外側

r2 = intensity_array(i,5) / intensity_array(i,4); % 核の2ピクセル外側 / 核の1ピクセル外側

r3 = intensity_array(i,6) / intensity_array(i,5); % 核の3ピクセル外側 / 核の2ピクセル外側

min_ratio = min([r0,r1,r2,r3]);

if min_ratio < 0.85

cells(i) = 2; % NLSと断定

continue;

end

% (核の1ピクセル外側 / 核内全体) < 0.9 ならNES,CAAXではないと判断

if r0 * r1 < 0.90

cells(i) = 5; % 判定不可

continue;

end

% 細胞がNESあるいはCAAXだと仮定して細胞質領域(cytoplasm_region)を求め、判定

grown_region = FRETImageProcess2.RegionGrowing(img, nucleus_region);

cytoplasm_region = grown_region ~= nucleus_region;

% 細胞質の面積 < 核内の面積 * 1.5 ならNES,CAAXではないと判断

if sum(sum(cytoplasm_region)) < sum(sum(nucleus_region)) * 1.5

cells(i) = 5; % 判定不可

continue;

end

mean_cytoplasm_intensity = mean(img(cytoplasm_region));

% 細胞内のintensityのSDをとる

sd_of_intensity = std(double(img(grown_region)));

% 核内intensityのエッジ(微分)のSDをとる

sd_of_differential_nuc = std(double(differential_img(nucleus_region)));

% sd_array(j) = sd_of_intensity; j = j + 1;

% 以前はSD_NES = 120, SD_CAAX = 60で固定

% 細胞内のSDと核内の微分SDで判断

if (sd_of_intensity > SD_NES) && (mean_cytoplasm_intensity > mean_nucleus_intensity)

if sd_of_differential_nuc > SD_NES * 2

cells(i) = 3; % NESと断定

continue;

end

elseif sd_of_intensity < SD_CAAX && (mean_cytoplasm_intensity >= mean_nucleus_intensity)

cells(i) = 4; % CAAXと断定

continue;

end

% ここまでで断定できなければ判定不可

cells(i) = 5; % 判定不可

end

% sd_array = sd_array(1:j-1);

% 核の大きさやintensityによってノイズをふるいにかける

mean_size = mean(nucleus_size_array(2:length(nucleus_size_array))); % 行列の1番目は背景分(0)なので除く

NLS_mean_intensity = mean(nucleus_intensity_array(cells == 2));

NES_mean_intensity = mean(nucleus_intensity_array(cells == 3));

CAAX_mean_intensity = mean(nucleus_intensity_array(cells == 4));

for i = 2:length(cells)

if (nucleus_size_array(i) < mean_size / 1.7) || (nucleus_size_array(i) > mean_size * 1.7)

cells(i) = 5; % サイズが平均より大きく離れていたら判定不可

end

if (cells(i) == 2) && ((nucleus_intensity_array(i) < NLS_mean_intensity / 1.7) || (nucleus_intensity_array(i) > NLS_mean_intensity * 1.7))

cells(i) = 5; % NLSのうち、intensityがNLSの平均より大きく離れていたら判定不可

elseif (cells(i) == 3) && ((nucleus_intensity_array(i) < NES_mean_intensity / 1.7) || (nucleus_intensity_array(i) > NES_mean_intensity * 1.7))

cells(i) = 5; % NESのうち、intensityがNESの平均より大きく離れていたら判定不可

elseif (cells(i) == 4) && ((nucleus_intensity_array(i) < CAAX_mean_intensity / 1.7) || (nucleus_intensity_array(i) > CAAX_mean_intensity * 1.7))

cells(i) = 5; % CAAXのうち、intensityがCAAXの平均より大きく離れていたら判定不可

end

end

% SortMatrix = SegmentationMatrix;

% for i = 2:length(cells)

% SortMatrix(SortMatrix==i) = cells(i); % NLS,NES,CAAX,判定不可で色分け

% end

% figure, imshow(label2rgb(SortMatrix,'jet','w','shuffle'));

SortArray = cells;

end

% 各細胞のIntensityを出力する領域を取得(ノイズを除いた領域)

function RegionForOutput = RegionForOutput(Imaging_Info, Tiff_Array, Position, WaveName, SegmentationMatrix, SortArray)

% 指定したPosition, WaveNameの画像を全timepoint分読み込み

height = size(Tiff_Array{1,1,1}, 1);

width = size(Tiff_Array{1,1,1}, 2);

imgarray = zeros(height, width, Imaging_Info.timepoints, 'uint16');

for i = 1:Imaging_Info.timepoints

imgarray(:,:,i) = FRETImageProcess2.GetImage(Imaging_Info, Tiff_Array, i, Position, WaveName);

end

% maximum imageとminimum imageを求めてそのsubtractを計算(noiseが浮き彫りになる)

maximum = max(imgarray, [], 3);

minimum = min(imgarray, [], 3);

subtract = maximum - minimum;

% subtractのintensity分布を計算

m = max(max(subtract));

distribution = zeros(m+1,2);

distribution(:,1) = 0:m;

for i = 1:size(subtract,1)

for j = 1:size(subtract,2)

distribution(subtract(i,j)+1,2) = distribution(subtract(i,j)+1,2) + 1;

end

end

distribution(:,1) = 0:m;

% subtract intensityを100ごとに区切り、それぞれの範囲内のピクセル数を比較、比が1.5以下になればそれ以上のsubtract intensityはノイズとする

for i = 1:100:(m-199)

sum1 = sum(distribution(i:i+99, 2));

sum2 = sum(distribution(i+100:i+199, 2));

if sum1 / sum2 < 1.5

break;

end

end

noise_removed_region = subtract <= i+99;

% minimum imageとenabled_regionからRegionForOutputを求める

% イメージング中に細胞が動いたり分裂したりする部分を除く

resultregion = SegmentationMatrix * 0 + 1; % SegmentationMatrixと同じサイズの1の行列(1は背景)

for i = 2:length(SortArray) % SortArray(1)は背景

% 核の領域を取得(enabled_regionに限る)

nucleus_region = SegmentationMatrix == i;

nucleus_region = imdilate(nucleus_region, strel('disk',1)); % 境界部が含まれないので拡張

nucleus_region = nucleus_region & noise_removed_region; % ノイズ領域を除く

if SortArray(i) == 2 % NLS

% 核内のintensityの平均値を求める

mean_int = mean(minimum(nucleus_region));

% 平均値より1.2倍以上低いピクセルは除く(細胞が動いた時などの影響)

outputregion = (minimum .* uint16(nucleus_region)) > mean_int / 1.2;

resultregion(outputregion) = i;

elseif SortArray(i) == 3 % NES

% 核の1~2ピクセル周辺のintensityの平均値を求める

periphery_region = imdilate(nucleus_region, strel('disk',2)) ~= nucleus_region;

mean_int = mean(minimum(periphery_region));

% 平均値より1.2倍以上低いピクセルは除く(細胞が動いた時などの影響)

outputregion = (minimum .* uint16(periphery_region)) > mean_int / 1.2;

resultregion(outputregion) = i;

elseif SortArray(i) == 4 % CAAX

% 核内のintensityの平均値を求める

mean_int = mean(minimum(nucleus_region));

% 平均値より1.2倍以上低いピクセルは除く(細胞が動いた時などの影響)

outputregion = (minimum .* uint16(nucleus_region)) > mean_int / 1.2;

resultregion(outputregion) = i;

end

end

RegionForOutput = resultregion;

end % RegionForOutput

% RegionForOutputに基づいてSortArrayを修正する

function ModifiedSortArray = ModifySortArray(Imaging_Info, Tiff_Array, Position, WaveName, SegmentationMatrix, SortArray, RegionForOutput)

% 指定したPosition, WaveNameの画像を全timepoint分読み込み

height = size(Tiff_Array{1,1,1}, 1);

width = size(Tiff_Array{1,1,1}, 2);

imgarray = zeros(height, width, Imaging_Info.timepoints, 'uint16');

for i = 1:Imaging_Info.timepoints

imgarray(:,:,i) = FRETImageProcess2.GetImage(Imaging_Info, Tiff_Array, i, Position, WaveName);

end

% minimum imageを求める

minimum_image = min(imgarray, [], 3);

new_sortarray = SortArray;

for i = 2:length(SortArray) % SortArray(1)は背景

% 1細胞についての出力領域が5ピクセル以下なら除外

if sum(sum(RegionForOutput == i)) <= 5

new_sortarray(i) = 5; % 判定不可

end

% % NLSをNESと誤判定したものを修正する(NLSの隣に明るい死細胞があるとが判定されうる)

% % minimum imageにおいて核内のintensityが出力領域のintensityより1.5倍以上明るければ修正

% nucleus_region = (SegmentationMatrix == i);

% output_region = (RegionForOutput == i);

% if mean(minimum_image(nucleus_region)) > mean(minimum_image(output_region)) * 1.5

% new_sortarray(i) = 5;

% end

end

ModifiedSortArray = new_sortarray;

% SortMatrix = SegmentationMatrix;

% for i = 2:length(new_sortarray)

% SortMatrix(SortMatrix==i) = new_sortarray(i); % NLS,NES,CAAX,判定不可で色分け

% end

% figure, imshow(label2rgb(SortMatrix,'jet','w','shuffle'));

end

% NLSの細胞のintesityを出力((NLSの細胞数)行 x 1列)

function NLSIntensities = OutputNLSIntensity(FRETimage, RegionForOutput, SortArray)

if strcmp(class(FRETimage), 'Tiff')

img = read(FRETimage);

else

img = uint16(round(FRETimage));

end

numofNLS = sum(SortArray == 2); % 2:NLS , 3:NES , 4:CAAX

output = zeros(numofNLS, 1);

j = 0;

for i = 2:length(SortArray)

if SortArray(i) == 2 % NLS

% 核内の平均intensityを出力

j = j + 1;

output(j) = mean(img(RegionForOutput == i));

end

end

NLSIntensities = output;

end

% NESの細胞のintesityを出力((NESの細胞数)行 x 1列)

function NESIntensities = OutputNESIntensity(FRETimage, RegionForOutput, SortArray)

if strcmp(class(FRETimage), 'Tiff')

img = read(FRETimage);

else

img = uint16(round(FRETimage));

end

numofNES = sum(SortArray == 3); % 2:NLS , 3:NES , 4:CAAX

output = zeros(numofNES, 1);

j = 0;

for i = 2:length(SortArray)

if SortArray(i) == 3 % NES

% 核の1~2ピクセル周辺の平均intensityを出力

j = j + 1;

output(j) = mean(img(RegionForOutput == i));

end

end

NESIntensities = output;

end

% CAAXの細胞のintesityを出力((CAAXの細胞数)行 x 1列)

function CAAXIntensities = OutputCAAXIntensity(FRETimage, RegionForOutput, SortArray)

if strcmp(class(FRETimage), 'Tiff')

img = read(FRETimage);

else

img = uint16(round(FRETimage));

end

numofCAAX = sum(SortArray == 4); % 2:NLS , 3:NES , 4:CAAX

output = zeros(numofCAAX, 1);

j = 0;

for i = 2:length(SortArray)

if SortArray(i) == 4 % CAAX

% 核内の平均intensityを出力

j = j + 1;

output(j) = mean(img(RegionForOutput == i));

end

end

CAAXIntensities = output;

end

end % method

end % classdef