feat: cDNA微阵列图像处理作业 - Python实现
实现内容: - 网格划分:投影分析 + 自相关估周期 + 白顶帽去背景 + 质心提取 - 三种阈值分割:人工阈值、Otsu自动阈值、迭代阈值 - TV去噪(Chambolle投影算法) - 后处理:去小连通域 + 保留最大连通域 - 完整可视化:网格叠加、阈值对比、收敛曲线、分割结果 参考MATLAB代码:NewGridAndCV/demo_GriddingAndCV.m
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
%% Microarray Spot Finding Example
|
||||
% This example shows a simple method for locating spots on a microarray and
|
||||
% extracting the intensties of the spots. It can be downloaded from *MATLAB
|
||||
% Central*.
|
||||
% http://www.mathworks.com/matlabcentral
|
||||
%
|
||||
% Copyright 2004-2010 RBemis The MathWorks, Inc.
|
||||
|
||||
%% Start with clean slate
|
||||
clear %empty workspace (no variables)
|
||||
close all %no figures
|
||||
clc %empty command window
|
||||
|
||||
%% Read image file
|
||||
% MATLAB can read many standard image formats including TIFF, GIF and BMP
|
||||
% using the |imread| command. In addition, the *Image Procesing Toolbox*
|
||||
% provides support for working with specialized image file formats such as
|
||||
% DICOM. This microarray image was stored as a J-PEG file. The image is
|
||||
% much larger than the screen size, so |imshow| scales it down to fit and
|
||||
% let's you know with a warning message.
|
||||
% x = imread('MicroArraySlide.JPG');
|
||||
% imageSize = size(x)
|
||||
% screenSize = get(0,'ScreenSize')
|
||||
%
|
||||
% iptsetpref('ImshowBorder','tight')
|
||||
% imshow(x)
|
||||
% title('original image')
|
||||
|
||||
%% Crop specified region
|
||||
% Next we use |imcrop| to extract a region of interest. You can repeat this
|
||||
% for all print-tip blocks for a full microarray study.
|
||||
% y = imcrop(x,[622 2467 220 227]);
|
||||
|
||||
|
||||
y=imread('test.tif');
|
||||
% y=imread('cDNA.png');
|
||||
% y=imread('test001.tif');
|
||||
% y = imread('C:\Users\Administrator\Desktop\中国生物医学工程学报(实验结果对比)\实验二\test001.tif');
|
||||
% y = imread('C:\Users\Administrator\Desktop\中国生物医学工程学报(实验结果对比)\实验三\test003.tif');
|
||||
f1 = figure('position',[40 46 285 280]);
|
||||
imshow(y)
|
||||
|
||||
%% Display red & green layers
|
||||
% This image was stored in RGB format. We are only interested in the red
|
||||
% and green planes. To extract the red plane, simply index layer 1. For the
|
||||
% green plane, layer 2. Custom colormaps make visualization more intuitive.
|
||||
% Notice that spot shapes are not necessarily the same in both colors.
|
||||
f2 = figure('position',[265 163 647 327]);
|
||||
subplot(121)
|
||||
redMap = gray(256);
|
||||
redMap(:,[2 3]) = 0;
|
||||
subimage(y(:,:,1),redMap)
|
||||
axis off
|
||||
title('red (layer 1)')
|
||||
subplot(122)
|
||||
greenMap = gray(256);
|
||||
greenMap(:,[1 3]) = 0;
|
||||
subimage(y(:,:,2),greenMap)
|
||||
axis off
|
||||
title('green (layer 2)')
|
||||
|
||||
%% Convert RGB image to grayscale for spot finding
|
||||
% Initially we care more about where the spots are located than their red
|
||||
% and green intensities. Converting from RGB color to grayscale allows us
|
||||
% to focus first on spot locations.
|
||||
z = rgb2gray(y);
|
||||
figure(f1)
|
||||
imshow(z)
|
||||
|
||||
%% Create horizontal profile
|
||||
% We are looking for a regular grid of spots so we start by looking at the
|
||||
% mean intensity for each column of the image. This will help us identify
|
||||
% where the centres of the spots are and where the gaps between the spots
|
||||
% can be found.
|
||||
xProfile = mean(z);
|
||||
f2 = figure('position',[39 346 284 73]);
|
||||
plot(xProfile)
|
||||
title('horizontal profile')
|
||||
axis tight
|
||||
|
||||
%% Estimate spot spacing by autocorrelation
|
||||
% Ideally the spots would be periodicaly spaced consistently printed, but
|
||||
% in practice they tend to have different sizes and intensities, so the
|
||||
% horizontal profile is irregular. We can use autocorrelation to enhance
|
||||
% the self similarity of the profile. The smooth result promotes peak
|
||||
% finding and estimation of spot spacing. The *Signal Processing Toolbox*
|
||||
% allows easy computation of the autocorrelation function using the |xcov|
|
||||
% command.
|
||||
|
||||
ac = xcov(xProfile); %unbiased autocorrelation
|
||||
f3 = figure('position',[-3 427 569 94]);
|
||||
plot(ac)
|
||||
s1 = diff(ac([1 1:end])); %left slopes
|
||||
s2 = diff(ac([1:end end])); %right slopes
|
||||
maxima = find(s1>0 & s2<0); %peaks
|
||||
estPeriod = round(median(diff(maxima))) %nominal spacing
|
||||
hold on
|
||||
plot(maxima,ac(maxima),'r^')
|
||||
hold off
|
||||
title('autocorrelation of profile')
|
||||
axis tight
|
||||
|
||||
%% Remove background morphologically
|
||||
% We can use the spacing estimate to help design a filter to remove the
|
||||
% background noise from the intensity profile. We do this with the
|
||||
% |imtophat| function from the *Image Processing Toolbox*. The |strel|
|
||||
% command creates a simple rectangular 1D window or line shaped structuring
|
||||
% element.
|
||||
seLine = strel('line',estPeriod,0);
|
||||
xProfile2 = imtophat(xProfile,seLine);
|
||||
f4 = figure('position',[40 443 285 76]);
|
||||
plot(xProfile2)
|
||||
title('enhanced horizontal profile')
|
||||
axis tight
|
||||
|
||||
%% Segment peaks
|
||||
% Now that we have clean and anchored gaps between the peaks, we can number
|
||||
% each peak region with the |bwlabel| command. These regions were segmented
|
||||
% by thresholding with |im2bw|. The threshold value was automatically
|
||||
% determined by statistical properties of the data using |graythresh|. This
|
||||
% is a good example of image processing techniques are often useful for 1D
|
||||
% data analysis.
|
||||
level = graythresh(xProfile2/255)*255
|
||||
bw = im2bw(xProfile2/255,level/255);
|
||||
L = bwlabel(bw);
|
||||
f5 = figure('position',[40 540 285 70]);
|
||||
plot(L)
|
||||
axis tight
|
||||
title('labelled regions')
|
||||
|
||||
%% Locate centers
|
||||
% We can extract the centroids of the peaks. These correspond to the
|
||||
% horizontal centres of the spots. This is a common blob analysis or
|
||||
% feature extraction task that can be done with |regionprops|.
|
||||
stats = regionprops(L);
|
||||
centroids = [stats.Centroid];
|
||||
xCenters = centroids(1:2:end)
|
||||
figure(f5)
|
||||
hold on
|
||||
plot(xCenters,1:max(L),'ro')
|
||||
hold off
|
||||
title('region centers')
|
||||
|
||||
%% Determine divisions between spots
|
||||
% The midpoints between adjacent peaks provides grid point locations.
|
||||
gap = diff(xCenters)/2;
|
||||
first = xCenters(1)-gap(1);
|
||||
xGrid = round([first xCenters(1:end)+gap([1:end end])])
|
||||
figure(f2)
|
||||
for i=1:length(xGrid)
|
||||
line(xGrid(i)*[1 1],ylim,'color','m')
|
||||
end
|
||||
title('vertical separators')
|
||||
|
||||
%% Transpose and repeat
|
||||
% We just did the analysis on the vertical grid. Now we want to do the same
|
||||
% for the horizontal spacing. To do this, we simply transpose the image and
|
||||
% repeat all the steps used above. This time without intermediate graphics
|
||||
% display commands in order to summarize the mathematical steps of this
|
||||
% algorithm.
|
||||
|
||||
yProfile = mean(z'); %peak profile
|
||||
ac = xcov(yProfile); %cross correlation
|
||||
p1 = diff(ac([1 1:end]));
|
||||
p2 = diff(ac([1:end end]));
|
||||
maxima = find(p1>0 & p2<0); %peak locations
|
||||
estPeriod = round(median(diff(maxima))) %spacing estimate
|
||||
seLine = strel('line',estPeriod,0);
|
||||
yProfile2 = imtophat(yProfile,seLine); %background removed
|
||||
level = graythresh(yProfile2/255); %automatic threshold level
|
||||
bw = im2bw(yProfile2/255,level); %binarized peak regions
|
||||
L = bwlabel(bw); %labeled regions
|
||||
stats = regionprops(L);
|
||||
centroids = [stats.Centroid]; %centroids
|
||||
yCenters = centroids(1:2:end) %Y parts only
|
||||
gap = diff(yCenters)/2; %inner region half widths
|
||||
first = yCenters(1)-gap(1);
|
||||
|
||||
% list defining vertical boundaries between spot regions
|
||||
yGrid = round([first yCenters(1:end)+gap([1:end end])])
|
||||
|
||||
%% Put bounding boxes around each spot
|
||||
% We have now found the rectangular grid. Using pairs of neighboring grid
|
||||
% points we can form bounding box regions to address each spot
|
||||
% individually. The position and size coordinates of each bounding box were
|
||||
% tabulated for convenience into a 4-column matrix called |ROI|, which
|
||||
% stands for regions of interest.
|
||||
% figure(f1)
|
||||
figure()
|
||||
imshow(z)
|
||||
line(xGrid'*[1 1],yGrid([1 end]),'color','b')
|
||||
line(xGrid([1 end]),yGrid'*[1 1],'color','b')
|
||||
[X,Y] = meshgrid(xGrid(1:end-1),yGrid(1:end-1)); %xGrid和yGrid中存储了分格子的数据
|
||||
[dX,dY] = meshgrid(diff(xGrid),diff(yGrid));
|
||||
ROI = [X(:) Y(:) dX(:) dY(:)];
|
||||
% first few rows of ROI table
|
||||
ROI(1:5,:)
|
||||
%%
|
||||
%
|
||||
I=y;
|
||||
% location_row=xGrid;
|
||||
% location_col=yGrid;
|
||||
|
||||
location_row=yGrid;
|
||||
location_col=xGrid;
|
||||
|
||||
for ii = 1:length(location_row)-1
|
||||
for jj = 1: length(location_col)-1
|
||||
subimage = I([location_row(ii):location_row(ii+1)],[location_col(jj):location_col(jj+1)],:);%从I中取出每个grid的数据
|
||||
subimage_double = double(subimage);
|
||||
|
||||
%%%% 转换数据到[0,1]之间,然后转换到[0,255]之间
|
||||
sumimage_01 = (subimage_double-min(subimage_double(:)))./max(subimage_double(:))-min(subimage_double(:)); %将每个grid的数据转换到[0,1]之间
|
||||
% subimage_norm = uint8(255*sumimage_01);%原文
|
||||
subimage_norm = uint8(255*sumimage_01);
|
||||
|
||||
%%%% TV去噪
|
||||
subimage_norm(:,:,1)= tvdenoise(double(subimage_norm(:,:,1)),0.01);
|
||||
subimage_norm(:,:,2)= tvdenoise(double(subimage_norm(:,:,2)),0.01);
|
||||
subimage_norm(:,:,3)= tvdenoise(double(subimage_norm(:,:,3)),0.01);
|
||||
|
||||
I_norm([location_row(ii):location_row(ii+1)],[location_col(jj):location_col(jj+1)],:)=subimage_norm;%每个grid的数据
|
||||
|
||||
|
||||
|
||||
%%
|
||||
%用CV方法进行分割
|
||||
|
||||
if mean(mean(subimage_norm(:,:,1)))<5 %%如果均值小于5,增强5图像
|
||||
subimage_norm=5*subimage_norm;
|
||||
else if mean(mean(subimage_norm(:,:,1)))<30 %%如果均值小于30,增强1.5图像
|
||||
subimage_norm=1.5*subimage_norm;
|
||||
end
|
||||
end
|
||||
|
||||
iter=500;
|
||||
dt=0.1;
|
||||
u0=cvseg(subimage_norm,iter,dt); %C-V水平集分割
|
||||
% u1=im2bw(u0);
|
||||
|
||||
%非数字的点设为默认值0
|
||||
[m_u0,n_u0]=size(u0);
|
||||
for i=1:m_u0
|
||||
for j=1:n_u0
|
||||
if(isnan(u0(i,j)))
|
||||
u0(i,j)=0;
|
||||
end
|
||||
end
|
||||
end
|
||||
% subimage_bw=u0;
|
||||
%若最后一列的第一个点或最后一个点为白色,则取反
|
||||
u1=u0;
|
||||
if(u1(end,1)==1 || u1(end,end))
|
||||
u2=1-u1;
|
||||
else
|
||||
u2=u1;
|
||||
end
|
||||
subimage_bw=u2;
|
||||
|
||||
% subimage_bw为获得的二值图像,即为传递到下一步的图像
|
||||
%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%分割结束%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
I_bw([location_row(ii):location_row(ii+1)],[location_col(jj):location_col(jj+1)],:)=subimage_bw;%每个grid的数据;
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
figure,imshow(I_bw)
|
||||
%显示与原图大学相等的二值图像
|
||||
all_bw=zeros(size(y(:,:,1)));
|
||||
all_bw(1:location_row(end),1:location_col(end))=I_bw;
|
||||
figure(),imshow(all_bw)
|
||||
%%
|
||||
I_bw1=all_bw;
|
||||
I_bw_01=choice(I_bw1,100); %%剔除面积大于100的目标(100仅为本次设定的阈值),这里最好用直方图的方法确定阈值,则更具普适性
|
||||
figure(),imshow(I_bw_01);
|
||||
%%
|
||||
num_sub_I_bw_02=0;
|
||||
for ii = 1:length(location_row)-1
|
||||
for jj = 1: length(location_col)-1
|
||||
sub_I_bw_01 = I_bw_01([location_row(ii):location_row(ii+1)],[location_col(jj):location_col(jj+1)],:);
|
||||
sub_I_bw_02=choosemaxobj(sub_I_bw_01,8);%剔除面积小于20的点
|
||||
|
||||
[m,n]=size(sub_I_bw_02);
|
||||
for i=1:m
|
||||
for j=1:n
|
||||
if(sub_I_bw_02(1,j)==1 || sub_I_bw_02(i,1)==1|| sub_I_bw_02(m,j)==1 || sub_I_bw_02(i,n)==1)
|
||||
num_sub_I_bw_02=num_sub_I_bw_02+1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(num_sub_I_bw_02>10)
|
||||
sub_I_bw_02=zeros(size(sub_I_bw_02));
|
||||
end
|
||||
|
||||
num_sub_I_bw_02=0;%每次计算完毕清零
|
||||
I_bw_Last_01([location_row(ii):location_row(ii+1)],[location_col(jj):location_col(jj+1)],:)=sub_I_bw_02;%每个grid的数据;
|
||||
end
|
||||
end
|
||||
all_bw_01=zeros(size(y(:,:,1)));
|
||||
all_bw_01(1:location_row(end),1:location_col(end))=I_bw_Last_01;
|
||||
figure(),imshow(all_bw_01);
|
||||
Reference in New Issue
Block a user