Multi-Scale Turing Patterns Generator
Inspired by: http://www.jonathanmccabe.com/Cyclic_Symmetric_Multi-Scale_Turing_Patterns.pdf
Sources:
function turing_patterns_demo()
Options
sz = 512; % image size, should be 2^n nscales = 6; % number of pyramid levels, less than log2(sz) write_vid = true; % whether to save as video
Initialize
a = rand(sz,sz); ms = zeros(sz,sz,nscales); vs = zeros(sz,sz,nscales); [R,C] = ndgrid(1:sz);
Prepare plot
hImg = imshow(a);
title('frame 0')
Prepare video writer
if write_vid if true % builtin MJPG encoder, should work across all systems vidext = 'avi'; fourcc = 'MJPG'; else % FFmpeg in OpenCV can use OpenH264 for encoding H.264, % download binaries and set OPENH264_LIBRARY environment variable % https://github.com/opencv/opencv/tree/3.3.1/3rdparty/ffmpeg % https://github.com/cisco/openh264/releases vidext = 'mp4'; fourcc = 'H264'; end vidfile = fullfile(tempdir(), ['turing.' vidext]); vid = cv.VideoWriter(vidfile, [sz sz], 'FourCC',fourcc); assert(vid.isOpened(), 'Could not open output video'); end
Main loop
counter = 0; while ishghandle(hImg) counter = counter + 1; if counter > 100, break; end % update pattern a_lods = cv.buildPyramid(a, 'MaxLevel',nscales); for i=1:nscales [ms(:,:,i), vs(:,:,i)] = process_scale(a_lods, i); end [~,mi] = min(vs, [], 3); mi = sub2ind([sz sz nscales], R, C, mi); a = a + ms(mi) * 0.025; a = (a - min(a(:))) / (max(a(:)) - min(a(:))); % write video frame if write_vid frame = repmat(uint8(a*255), [1 1 3]); % 8-bit RGB vid.write(frame); end % show result set(hImg, 'CData',a); title(sprintf('frame %d',counter)); drawnow; end
Finalize video
if write_vid vid.release(); fprintf('Video saved: %s\n', vidfile); if ispc() && ~mexopencv.isOctave() %HACK: WINOPEN not implemented in Octave winopen(vidfile); end end
Video saved: C:\Users\Amro\AppData\Local\Temp\turing.avi
end
Helper function
function [m,v] = process_scale(a_lods, lod) d = a_lods{lod} - cv.pyrUp(a_lods{lod+1}); for i=2:lod d = cv.pyrUp(d); end m = sign(d); v = cv.GaussianBlur(d.*d, 'KSize',[3 3]); end