我们经常看到一些文献中对细胞或者粒子的运动轨迹进行上色,不同的颜色对应着不同的时间。一纯色的轨迹实现起来很方便,彩色的轨迹如何实现呢?本文使用imageJ获取轨迹数据,使用matlab对轨迹进行上色。结果如下:
1. imageJ 导入图像
导入视频,本案例使用的.mp4格式视频。需要安装一个插件,FFmpeg。
打开imageJ,找到更新页面(Help->Update…)
点击 Manage Update Sites
找到FFMPEG插件,并勾选,然后点击App and Close
最后点击Apply Changes
等待安装完成并重启软件后,就能找到插件了
点击Movie(FFMPEG),将自己的.mp4文件进行导入。
注意需要取消勾选Use virtual stack,否则会报错。
2. imageJ轨迹追踪
2.1 手动轨迹追踪
点击Plugins->Tracking->Manual Tracking,进行手动轨迹追踪
根据自己视频需求,设置相关参数。如果只进行轨迹追踪,不需要特殊设置。然后点击Add track
使用鼠标左键点击你关注的物体或者粒子,就能够得到每一帧图片中这个物体在整个图像中的X Y坐标,这些X Y坐标序列就是该物体的轨迹。后续我们将使用这些轨迹在Matlab中进行上色。
当完整所有帧中的轨迹点选,就会出现一条轨迹曲线。本文仅单个物体的轨迹追踪为例,如果需要同时追踪多个物体,需要再次点击Add track,然后重新从第一帧开始点取。
我们将得到数据保存下载,之后导入matlab中
2.2 自动轨迹追踪
随后添加
3. 在Maltab中为轨迹上色
首先读取图像数据以及 ImageJ导出的数据
clear all
clc
%% 读取数据
% 读取视频文件
videoFile = '示例视频.mp4';
video = VideoReader(videoFile);
% 创建一个视频写入对象,用于保存带有轨迹的视频
outputVideoFile = 'OutPut-示例视频.mp4';
outputVideo = VideoWriter(outputVideoFile, 'MPEG-4');
open(outputVideo);
% 读取CSV文件
data = readtable('data.csv');
% 获取x和y坐标数据,假设第一列是x坐标,第二列是y坐标
x = data{:, 3};
y = data{:, 4};
SliceN=data{:, 2};
trackNum=length(SliceN);
创建窗口用于实时显示绘制过程,可以修改colors来改变轨迹的映射颜色,也可以修改轨迹粗细
%%
% 创建一个图形窗口用于显示视频
hFig = figure;
% 获取jet颜色映射
cmap = jet;
% 归一化数据到[0, 1]
dataNormalized = (SliceN - min(SliceN)) / (max(SliceN) - min(SliceN));
% 使用round来确保索引是整数
colorIdx = round(dataNormalized * (size(cmap, 1) - 1)) + 1;
% 获取对应的颜色
colors = cmap(colorIdx, :);
% 轨迹粗细
lineWidth = 6; % 可以设置为您需要的值
% 轨迹点大小
markerSize = lineWidth * 3; % 确保点足够大以覆盖线段之间的间隙
对每一帧进行轨迹与图像叠加
while hasFrame(video)
% 读取一帧
frame = readFrame(video);
% 在当前帧上绘制轨迹
imshow(frame);
hold on; % 保持当前帧的图像,以便在上面绘制轨迹
% 获取当前帧号
frameNumber = video.CurrentTime * video.FrameRate;
% 限制轨迹到当前帧号
currentX = x(SliceN <= frameNumber);
currentY = y(SliceN <= frameNumber);
% 在帧上添加轨迹
for k = 1:length(currentX)-1
% 绘制点以覆盖线段间的间隙
plot(currentX(k), currentY(k), '.', 'MarkerSize', markerSize, 'Color', colors(k, :));
line([currentX(k) currentX(k+1)], [currentY(k) currentY(k+1)], 'Color', colors(k, :), 'LineWidth', lineWidth,'LineJoin','round');
end
hold off; % 结束绘图,以便下一帧可以重新开始绘制
% 将带轨迹的帧写入输出视频
frameWithPath = getframe(gca);
writeVideo(outputVideo, frameWithPath.cdata);
% 播放视频
drawnow;
end
% 关闭视频写入对象
close(outputVideo);
% 关闭图形窗口
close(hFig);
% 打开带轨迹的视频
implay(outputVideoFile);
轨迹上色结果如下。因为****上传文件大小限制,所以颜色会失真,实际效果很好。