我的问题涉及从电泳凝胶中提取特征(见下文)。在该凝胶中,从顶部装载DNA并使其在电压梯度下迁移。凝胶具有筛子,因此较小的分子比较长的分子迁移得更远,导致DNA长度分离。分子越高,它就越长。
在该图像中,有9个泳道,每个泳道都有独立的DNA来源。我有兴趣测量每条车道的平均位置(y轴上的值)。 我对图像处理很陌生,但我知道MATLAB,我可以用R来解决这个问题。如果有人能告诉我如何找到每条车道的平均值,我真的很感激。
答案 0 :(得分:5)
这是我的尝试。它要求凝胶很好(即直通道和凝胶不应旋转),但应该相当普遍地工作。请注意,需要调整两个与图像大小相关的参数,以使其适用于不同大小的图像。
%# first size-dependent parameter: should be about 1/4th-1/5th
%# of the lane width in pixels.
minFilterWidth = 10;
%# second size-dependent parameter for filtering the
%# lane profiles
gaussWidth = 5;
%# read the image, normalize to 0...1
img = imread('http://img823.imageshack.us/img823/588/gele.png');
img = rgb2gray(img);
img = double(img)/255;
%# Otsu thresholding to (roughly) find lanes
thMsk = img < graythresh(img);
%# count the mask-pixels in each columns. Due to
%# lane separation, there will be fewer pixels
%# between lanes
cts = sum(thMsk,1);
%# widen the local minima, so that we get a nice
%# separation between lanes
ctsEroded = imerode(cts,ones(1,minFilterWidth));
%# use imregionalmin to identify the separation
%# between lanes. Invert to get a positive mask
laneMsk = ~repmat(imregionalmin(ctsEroded),size(img,1),1);
带有将用于分析的车道的图像
%# for each lane, create an averaged profile
lblMsk = bwlabel(laneMsk);
nLanes = max(lblMsk(:));
profiles = zeros(size(img,1),nLanes);
midLane = zeros(1,nLanes);
for i = 1:nLanes
profiles(:,i) = mean(img.*(lblMsk==i),2);
midLane(:,i) = mean(find(lblMsk(1,:)==i));
end
%# Gauss-filter the profiles (each column is an
%# averaged intensity profile
G = exp(-(-gaussWidth*5:gaussWidth*5).^2/(2*gaussWidth^2));
G=G./sum(G);
profiles = imfilter(profiles,G','replicate'); %'
%# find the minima
[~,idx] = min(profiles,[],1);
%# plot
figure,imshow(img,[])
hold on, plot(midLane,idx,'.r')
答案 1 :(得分:4)
这是我用一个简单的模板来实现这一目的的交互方式:
% Load image
img = imread('gel.png');
img = rgb2gray(img);
% Identify lanes
imshow(img)
[x,y] = ginput;
% Invert image
img = max(img(:)) - img;
% Subtract background
[xn,yn] = ginput(1);
noise = img((yn-2):(yn+2), (xn-2):(xn+2));
noise = mean(noise(:));
img = img - noise;
% Calculate means
means = (1:size(img,1)) * double(img(:,round(x))) ./ sum(double(img(:,round(x))), 1);
% Plot
hold on
plot(x, means, 'r.')
答案 2 :(得分:4)
要做的第一件事是将RGB图像转换为灰度:
gr = rgb2gray(imread('gelk.png'));
然后,使用imhist
查看图像强度直方图。注意到有什么好玩的吗?使用imcontrast(imshow(gr))
拉出对比度调整工具。我发现在主要强度峰值之后消除奇怪的东西是有益的。
图像处理任务本身可以分为几个步骤。
步骤1 可以“手动”完成,如果保证了车道宽度。如果没有,Hough transform提供的线路检测可能就是这样。图像处理工具箱上的文档有一个关于这个主题的非常好的教程。我的代码概括了该教程,为您的图像提供了更好的参数。我只用了几分钟,我相信你可以通过进一步调整参数来改善结果。
第2步可以通过几种方式完成。最简单的技术是Otsu用于阈值灰度图像的方法。此方法通过确定最小化 intra 类方差的阈值来工作,或者等效地,最大化 inter - 类方差。 Otsu的方法在MATLAB中作为graythresh
函数出现。如果Otsu的方法效果不佳,您可以尝试multi-level Otsu或其他一些histogram based threshold determination methods。
步骤3 。这就是我的代码所做的,虽然我已将检查限制在每个通道的中心列,以防分离关闭。我担心结果可能不如计算波段质心和使用它的位置那么好。
这是我的解决方案:
function [locations, lanesBW, lanes, cols] = segmentGel(gr)
%%# Detect lane boundaries
unsharp = fspecial('unsharp'); %# Sharpening filter
I = imfilter(gr,unsharp); %# Apply filter
bw = edge(I,'canny',[0.01 0.3],0.5); %# Canny edges with parameters
[H,T,R] = hough(bw); %# Hough transform of edges
P = houghpeaks(H,20,'threshold',ceil(0.5*max(H(:)))); %# Find peaks of Hough transform
lines = houghlines(bw,T,R,P,'FillGap',30,'MinLength',20); %# Use peaks to identify lines
%%# Plot detected lines above image, for quality control
max_len = 0;
imshow(I);
hold on;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
%# Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
%# Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
end
end
hold off;
%%# Use first endpoint of each line to separate lanes
cols = zeros(length(lines),1);
for k = 1:length(lines)
cols(k) = lines(k).point1(1);
end
cols = sort(cols); %# The lines are in no particular order
lanes = cell(length(cols)-1,1);
for k = 2:length(cols)
lanes{k-1} = im2double( gr(:,cols(k-1):cols(k)) ); %# im2double for compatibility with greythresh
end
otsu = cellfun(@graythresh,lanes); %# Calculate threshold for each lane
lanesBW = cell(size(lanes));
for k = 1:length(lanes)
lanesBW{k} = lanes{k} < otsu(k); %# Apply thresholds
end
%%# Use segmented bands to determine migration distance
locations = zeros(size(lanesBW));
for k = 1:length(lanesBW)
width = size(lanesBW{k},2);
[y,~] = find(lanesBW{k}(:,round(width/2))); %# Only use center of lane
locations(k) = mean(y);
end
我建议您在将其用于实际研究目的之前,不仅要仔细检查每个输出值,还要检查功能的每个步骤的结果。为了获得非常好的结果,您将不得不阅读有关Hough变换,Canny边缘检测和Otsu方法的一些信息,然后调整参数。您可能还必须改变车道的分裂方式;此代码假定在图像的任一侧检测到线条。
答案 3 :(得分:3)
让我添加另一个与@JohnColby的概念类似的实现,只是没有手动用户交互:
%# read image
I = rgb2gray(imread('gele.png'));
%# middle position of each lane
%# (assuming lanes are somewhat evenly spread and of similar width)
x = linspace(1,size(I,2),10);
x = round( (x(1:end-1)+x(2:end))./2 );
%# compute the mean value across those columns
m = mean(I(:,x));
%# find the y-indices of the mean values
[~,idx] = min( bsxfun(@minus, double(I(:,x)), m) );
%# show the result
figure(1)
imshow(I, 'InitialMagnification',100, 'Border','tight')
hold on, plot(x, idx, ...
'Color','r', 'LineStyle','none', 'Marker','.', 'MarkerSize',10)
并应用于较小的图片: