You are hereFeed aggregator

Feed aggregator

  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.
  • warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thor/Sites/modules/aggregator/aggregator.pages.inc on line 259.

Feret Diameter: Introduction

Matlab Image processing blog - 2017, September 29 - 13:23

This is the first of a few blog posts about object measurements based on a concept called the Feret diameter, sometimes called the caliper diameter. The diagram below illustrates the concept. Place the object to be measured inside the jaws of a caliper, with the caliper oriented at a specified angle. Close the jaws tightly on the object while maintaining that angle. The distance between the jaws is the Feret diameter at that angle.

Eventually, we'll examine several related measurements (and algorithms for computing them), like these.

Today, though, I'm just going to play around with a very small binary image. (Note: the pixelgrid function is a utility that I wrote. It's at the bottom of this post.)

bw = [ ... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]; imshow(bw) pixelgrid

I want to brute-force my to finding the two corners of the white blob that are farthest apart. Let's start by finding all the pixel corners. (I'll be using implicit expansion here, which works in R2016b or later.)

[y,x] = find(bw); hold on plot(x,y,'xb','MarkerSize',5) corners = [x y] + cat(3,[.5 .5],[.5 -.5],[-.5 .5],[-.5 -.5]); corners = permute(corners,[1 3 2]); corners = reshape(corners,[],2); corners = unique(corners,'rows'); plot(corners(:,1),corners(:,2),'sr','MarkerSize',5) hold off

Well, let's get away from pure brute force just a little. We really only need to look at the points that are part of the convex hull of all the corner points.

hold on k = convhull(corners); hull_corners = corners(k,:); plot(hull_corners(:,1),hull_corners(:,2),'r','LineWidth',3) plot(hull_corners(:,1),hull_corners(:,2),'ro','MarkerSize',10,'MarkerFaceColor','r') hold off

Now let's find which two points on the convex hull are farthest apart.

dx = hull_corners(:,1) - hull_corners(:,1)'; dy = hull_corners(:,2) - hull_corners(:,2)'; pairwise_dist = hypot(dx,dy); [max_dist,j] = max(pairwise_dist(:)); [k1,k2] = ind2sub(size(pairwise_dist),j); point1 = hull_corners(k1,:); point2 = hull_corners(k2,:); hold on plot([point1(1) point2(1)],[point1(2) point2(2)],'-db','LineWidth',3,'MarkerFaceColor','b') hold off

And the maximum distance is ...

max_dist max_dist = 10

(I thought I had made a mistake when I first saw this number come out to be an exact integer. But no, the answer is really 10.)

That's a pretty good start. I don't know exactly where I'll go with this topic next time. I'm making it up as I go.

function hout = pixelgrid(h) %pixelgrid Superimpose a grid of pixel edges on an image % pixelgrid superimposes a grid of pixel edges on the image in the % current axes. % % pixelgrid(h_ax) superimposes the grid on the image in the specified % axes. % % pixelgrid(h_im) superimposes the grid on the specified image. % % group = pixelgrid(___) returns an hggroup object that contains the two % lines that are used to draw the grid. One line is thick and darker, and % the other is thin and lighter. Using two contrasting lines in this way % guarantees that the grid will be visible regardless of pixel colors. % % EXAMPLES % % Superimpose pixel grid on color image. Zoom in. % % rgb = imread('peppers.png'); % imshow(rgb) % pixelgrid % axis([440 455 240 250]) % % Change the colors and line widths of the pixel grid. % % rgb = imread('peppers.png'); % imshow(rgb) % h = pixelgrid; % axis([440 455 240 250]) % h.Children(1).Color = [178 223 138]/255; % h.Children(1).LineWidth = 2; % h.Children(2).Color = [31 120 180]/255; % h.Children(2).LineWidth = 4; % % LIMITATIONS % % This function is intended for use when looking at a zoomed-in image % region with a relatively small number of rows and columns. If you use % this function on a typical, full-size image without zooming in, the % image will not be visible under the grid lines. % % This function attempts to determine if MATLAB is running with a high % DPI display. If so, then it displays the pixel grid using thinner % lines. However, the method for detecting a high DPI display on works on % a Mac when Java AWT is available. % Steve Eddins % Copyright The MathWorks, Inc. 2017 if nargin < 1 him = findobj(gca,'type','image'); elseif strcmp(h.Type,'axes') him = findobj(h,'type','image'); elseif strcmp(h.Type,'image') him = h; else error('Invalid graphics object.') end if isempty(him) error('Image not found.'); end hax = ancestor(him,'axes'); xdata = him.XData; ydata = him.YData; [M,N,~] = size(him.CData); if M > 1 pixel_height = diff(ydata) / (M-1); else % Special case. Assume unit height. pixel_height = 1; end if N > 1 pixel_width = diff(xdata) / (N-1); else % Special case. Assume unit width. pixel_width = 1; end y_top = ydata(1) - (pixel_height/2); y_bottom = ydata(2) + (pixel_height/2); y = linspace(y_top, y_bottom, M+1); x_left = xdata(1) - (pixel_width/2); x_right = xdata(2) + (pixel_width/2); x = linspace(x_left, x_right, N+1); % Construct xv1 and yv1 to draw all the vertical line segments. Separate % the line segments by NaN to avoid drawing diagonal line segments from the % bottom of one line to the top of the next line over. xv1 = NaN(1,3*numel(x)); xv1(1:3:end) = x; xv1(2:3:end) = x; yv1 = repmat([y(1) y(end) NaN], 1, numel(x)); % Construct xv2 and yv2 to draw all the horizontal line segments. yv2 = NaN(1,3*numel(y)); yv2(1:3:end) = y; yv2(2:3:end) = y; xv2 = repmat([x(1) x(end) NaN], 1, numel(y)); % Put all the vertices together so that they can be drawn with a single % call to line(). xv = [xv1(:) ; xv2(:)]; yv = [yv1(:) ; yv2(:)]; hh = hggroup(hax); dark_gray = [0.3 0.3 0.3]; light_gray = [0.8 0.8 0.8]; if isHighDPI bottom_line_width = 1.5; top_line_width = 0.5; else bottom_line_width = 3; top_line_width = 1; end % When creating the lines, use AlignVertexCenters to avoid antialias % effects that would cause some lines in the grid to appear brighter than % others. line(... 'Parent',hh,... 'XData',xv,... 'YData',yv,... 'LineWidth',bottom_line_width,... 'Color',dark_gray,... 'LineStyle','-',... 'AlignVertexCenters','on'); line(... 'Parent',hh,... 'XData',xv,... 'YData',yv,... 'LineWidth',top_line_width,... 'Color',light_gray,... 'LineStyle','-',... 'AlignVertexCenters','on'); % Only return an output if requested. if nargout > 0 hout = hh; end end function tf = isHighDPI % Returns true if running with a high DPI default display. % % LIMITATION: Only works on a Mac with Java AWT available. In other % situations, this function always returns false. tf = false; if ismac if usejava('awt') sf = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice.getScaleFactor(); tf = sf > 1; end end end \n'); d.write(code_string); // Add copyright line at the bottom if specified. if (copyright.length > 0) { d.writeln(''); d.writeln('%%'); if (copyright.length > 0) { d.writeln('% _' + copyright + '_'); } } d.write('\n'); d.title = title + ' (MATLAB code)'; d.close(); } -->


Get the MATLAB code (requires JavaScript)

Published with MATLAB® R2017b

> % % Eventually, we'll examine several related measurements (and algorithms for % computing them), like these. % % <> % % Today, though, I'm just going to play around with a very small binary % image. (Note: the |pixelgrid| function is a utility that I wrote. It's at % the bottom of this post.) bw = [ ... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]; imshow(bw) pixelgrid %% % I want to brute-force my to finding the two % corners of the white blob that are farthest apart. Let's start by finding % all the pixel corners. (I'll be using % here, which works in R2016b or later.) [y,x] = find(bw); hold on plot(x,y,'xb','MarkerSize',5) corners = [x y] + cat(3,[.5 .5],[.5 -.5],[-.5 .5],[-.5 -.5]); corners = permute(corners,[1 3 2]); corners = reshape(corners,[],2); corners = unique(corners,'rows'); plot(corners(:,1),corners(:,2),'sr','MarkerSize',5) hold off %% % Well, let's get away from pure brute force just a little. We really only % need to look at the points that are part of the _convex hull_ of all the % corner points. hold on k = convhull(corners); hull_corners = corners(k,:); plot(hull_corners(:,1),hull_corners(:,2),'r','LineWidth',3) plot(hull_corners(:,1),hull_corners(:,2),'ro','MarkerSize',10,'MarkerFaceColor','r') hold off %% % Now let's find which two points on the convex hull are farthest apart. dx = hull_corners(:,1) - hull_corners(:,1)'; dy = hull_corners(:,2) - hull_corners(:,2)'; pairwise_dist = hypot(dx,dy); [max_dist,j] = max(pairwise_dist(:)); [k1,k2] = ind2sub(size(pairwise_dist),j); point1 = hull_corners(k1,:); point2 = hull_corners(k2,:); hold on plot([point1(1) point2(1)],[point1(2) point2(2)],'-db','LineWidth',3,'MarkerFaceColor','b') hold off %% % And the maximum distance is ... max_dist %% % (I thought I had made a mistake when I first saw this number come out to % be an exact integer. But no, the answer is really 10.) % % That's a pretty good start. I don't know exactly where I'll go with this % topic next time. I'm making it up as I go. %% function hout = pixelgrid(h) %pixelgrid Superimpose a grid of pixel edges on an image % pixelgrid superimposes a grid of pixel edges on the image in the % current axes. % % pixelgrid(h_ax) superimposes the grid on the image in the specified % axes. % % pixelgrid(h_im) superimposes the grid on the specified image. % % group = pixelgrid(___) returns an hggroup object that contains the two % lines that are used to draw the grid. One line is thick and darker, and % the other is thin and lighter. Using two contrasting lines in this way % guarantees that the grid will be visible regardless of pixel colors. % % EXAMPLES % % Superimpose pixel grid on color image. Zoom in. % % rgb = imread('peppers.png'); % imshow(rgb) % pixelgrid % axis([440 455 240 250]) % % Change the colors and line widths of the pixel grid. % % rgb = imread('peppers.png'); % imshow(rgb) % h = pixelgrid; % axis([440 455 240 250]) % h.Children(1).Color = [178 223 138]/255; % h.Children(1).LineWidth = 2; % h.Children(2).Color = [31 120 180]/255; % h.Children(2).LineWidth = 4; % % LIMITATIONS % % This function is intended for use when looking at a zoomed-in image % region with a relatively small number of rows and columns. If you use % this function on a typical, full-size image without zooming in, the % image will not be visible under the grid lines. % % This function attempts to determine if MATLAB is running with a high % DPI display. If so, then it displays the pixel grid using thinner % lines. However, the method for detecting a high DPI display on works on % a Mac when Java AWT is available. % Steve Eddins % Copyright The MathWorks, Inc. 2017 if nargin < 1 him = findobj(gca,'type','image'); elseif strcmp(h.Type,'axes') him = findobj(h,'type','image'); elseif strcmp(h.Type,'image') him = h; else error('Invalid graphics object.') end if isempty(him) error('Image not found.'); end hax = ancestor(him,'axes'); xdata = him.XData; ydata = him.YData; [M,N,~] = size(him.CData); if M > 1 pixel_height = diff(ydata) / (M-1); else % Special case. Assume unit height. pixel_height = 1; end if N > 1 pixel_width = diff(xdata) / (N-1); else % Special case. Assume unit width. pixel_width = 1; end y_top = ydata(1) - (pixel_height/2); y_bottom = ydata(2) + (pixel_height/2); y = linspace(y_top, y_bottom, M+1); x_left = xdata(1) - (pixel_width/2); x_right = xdata(2) + (pixel_width/2); x = linspace(x_left, x_right, N+1); % Construct xv1 and yv1 to draw all the vertical line segments. Separate % the line segments by NaN to avoid drawing diagonal line segments from the % bottom of one line to the top of the next line over. xv1 = NaN(1,3*numel(x)); xv1(1:3:end) = x; xv1(2:3:end) = x; yv1 = repmat([y(1) y(end) NaN], 1, numel(x)); % Construct xv2 and yv2 to draw all the horizontal line segments. yv2 = NaN(1,3*numel(y)); yv2(1:3:end) = y; yv2(2:3:end) = y; xv2 = repmat([x(1) x(end) NaN], 1, numel(y)); % Put all the vertices together so that they can be drawn with a single % call to line(). xv = [xv1(:) ; xv2(:)]; yv = [yv1(:) ; yv2(:)]; hh = hggroup(hax); dark_gray = [0.3 0.3 0.3]; light_gray = [0.8 0.8 0.8]; if isHighDPI bottom_line_width = 1.5; top_line_width = 0.5; else bottom_line_width = 3; top_line_width = 1; end % When creating the lines, use AlignVertexCenters to avoid antialias % effects that would cause some lines in the grid to appear brighter than % others. line(... 'Parent',hh,... 'XData',xv,... 'YData',yv,... 'LineWidth',bottom_line_width,... 'Color',dark_gray,... 'LineStyle','-',... 'AlignVertexCenters','on'); line(... 'Parent',hh,... 'XData',xv,... 'YData',yv,... 'LineWidth',top_line_width,... 'Color',light_gray,... 'LineStyle','-',... 'AlignVertexCenters','on'); % Only return an output if requested. if nargout > 0 hout = hh; end end function tf = isHighDPI % Returns true if running with a high DPI default display. % % LIMITATION: Only works on a Mac with Java AWT available. In other % situations, this function always returns false. tf = false; if ismac if usejava('awt') sf = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice.getScaleFactor(); tf = sf > 1; end end end ##### SOURCE END ##### 7426ac4b32424f798cb7fb50b402a56d -->

Categories: Blogs

New Deep Learning Blog on MATLAB Central

Matlab Image processing blog - 2017, September 22 - 11:23

I'd like to invite everyone to check out the new Deep Learning blog that just launched today on MATLAB Central.

I happen to know the author, and he's an OK fellow.

Categories: Blogs

Boring, complex and important: the deadly mix that blew up the open web

Cory Doctorow - 2017, September 21 - 11:11

On Monday, the World Wide Web Consortium published EME, a standard for locking up video on the web with DRM, allowing large corporate members to proceed without taking any steps to protect accessibility work, security research, archiving or innovation.


I spent years working to get people to pay attention to the ramifications of the effort, but was stymied by the deadly combination of an issue that was super-technical and complicated, as well as kind of boring (standards-making is a slow-moving, legalistic process).

This is really the worst kind of problem, an issue that matters but that requires a lot of technical knowledge and sustained attention to engage with. I wrote up a postmortem on the effort for Wired.


The W3C is a multistakeholder body based on consensus, and that means that members are expected to compromise to find common ground. So we returned with a much milder proposal: we’d stand down on objecting to EME, provided that the consortium promised only to invoke laws such as the DMCA in tandem with some other complaint, like copyright infringement. That meant studios and their technology partners could always sue when someone infringed copyright, or stole trade secrets, or interfered with contractual arrangements, but they would not be able to abuse the W3C process to claim the right to sue over otherwise legal activities, such as automatically analysing videos to prevent strobe effects from triggering seizures in people with photosensitive epilepsy.

This proposal was a way to get at the leadership’s objection: if the law was making the mischief, then let us take the law off the table (EFF is also suing the US government to get the law overturned, but that could take years, far too long in web-time). More importantly, if EME’s advocates refused to negotiate on this point, it would suggest that they planned on using the law to enforce “rights” that they really shouldn’t have, such as the right to decide who could adapt video for people with disabilities, or whether national archives could exercise their statutory rights to make deposit copies of copyrighted works.

But EME’s proponents – a collection of browser vendors, entertainment industry trade bodies, and companies selling products based on EME – refused to negotiate. After 90 days of desultory participation, the W3C leaders allowed the process to die. Despite this intransigence, the W3C executive renewed the EME working group’s charter and allowed it to continue its work, even as the cracks among the W3C’s membership on the standard’s fate deepened.

By the time EME was ready to publish, those cracks had deepened further. The poll results on EME showed the W3C was more divided on this matter than on any in its history. Again, the W3C leadership put its thumbs on the scales for the entertainment industry’s wish-lists over the open web’s core requirements, and overrode every single objection raised by the members.

Boring, complex and important: a recipe for the web’s dire future
[Cory Doctorow/Wired]

Categories: Blogs

Gray-scale pixel values in image regions

Matlab Image processing blog - 2017, September 11 - 13:26

Before I dive into today's topic, I want to invite you to come back to the MATLAB Central Blogs page in a couple of weeks. Look for something new to appear related to deep learning.

Earlier today, I was looking at recent image processing questions on MATLAB Answers, and I came across this question:

"Using regionprops to change intensity of blobs"

I thought to myself, "I bet I've written about something like before." It turns out that I have -- but it was more than ten years ago! It is ever-so-slightly possible that a couple of you have not been reading this blog that long, so I thought I would update the post for you today.

The function regionprops is very useful for measuring the properties of shapes in a binary image. There are documentation examples and product demos showing how to do this, and I've shown this function in action several times in this blog.

But sometimes I get questions about how to process pixel values in the "original" gray scale image. In other words, suppose your process is something like this:

  • Segment gray scale image to get a binary image of objects
  • Do something with the original gray scale pixel values corresponding to each blob in the binary image

This post is about how to do that last step. Let's start by creating some simple sample images to work with.

I = imread('coins.png'); imshow(I) bw = imbinarize(I); bw = imfill(bw, 'holes'); imshow(bw) title('Thresholded, with holes filled')

The key to processing the pixels in I using the blobs in bw is to use regionprops to get the 'PixelIdxList' for each blob.

s = regionprops(L, 'PixelIdxList') s = 10×1 struct array with fields: PixelIdxList s(1) ans = struct with fields: PixelIdxList: [2651×1 double]

s is a struct array. s(k).PixelIdxList is a vector of the linear indices of the k-th region. You can use these values to index directly into I. For example, here is the mean pixel value of the 3rd coin:

idx = s(3).PixelIdxList; mean(I(idx)) ans = 172.8769

You can also replace object pixel values in I by indexing on the left side of an assignment statement, like this:

% Turn the 4th coin white and the 5th coin black: J = I; J(s(4).PixelIdxList) = 255; J(s(5).PixelIdxList) = 0; imshow(J)

Here's a loop that replaces the pixel values for each coin by the mean pixel value for that coin:

F = I; for k = 1:numel(s) idx = s(k).PixelIdxList; F(idx) = mean(I(idx)); end imshow(F)

I'll finish with a question that Mat asked in a blog comment: "How can I find the location of the maximum pixel value in each labeled region?" Here's how to find the locations and then plot them on top of the original image. (In addition to 'PixelIdxList', I'll also ask regionprops for 'PixelList', which gives the x and y coordinates of each pixel in the region.)

s = regionprops(L, 'PixelIdxList', 'PixelList'); imshow(I) hold on for k = 1:numel(s) idx = s(k).PixelIdxList; pixels_in_region_k = I(idx); [max_value, max_idx] = max(pixels_in_region_k); max_location = s(k).PixelList(max_idx, :); plot(max_location(1),max_location(2),'o','MarkerSize',10,... 'MarkerFaceColor','w','MarkerEdgeColor','k') end hold off \n'); d.write(code_string); // Add copyright line at the bottom if specified. if (copyright.length > 0) { d.writeln(''); d.writeln('%%'); if (copyright.length > 0) { d.writeln('% _' + copyright + '_'); } } d.write('\n'); d.title = title + ' (MATLAB code)'; d.close(); } -->


Get the MATLAB code (requires JavaScript)

Published with MATLAB® R2017a

in a couple % of weeks. Look for something new to appear related to deep learning_. % % Earlier today, I was looking at on % MATLAB Answers, and I came across this question: % % % % I thought to myself, "I bet I've written about something like before." It % turns out that I have REPLACE_WITH_DASH_DASH but it was more than ten years ago! It is % ever-so-slightly possible that a couple of you have not been reading this % blog that long, so I thought I would update the post for you today. % % The function |regionprops| is very useful for measuring % the properties of shapes in a binary image. There are documentation % examples and product demos showing how to do this, and I've shown this % function in action several times in this blog. % % But sometimes I get questions about how to process pixel values in the % "original" gray scale image. In other words, suppose your process is % something like this: % % * Segment gray scale image to get a binary image of objects % * Do something with the original gray scale pixel values corresponding % to each blob in the binary image % % This post is about how to do that last step. Let's start by creating % some simple sample images to work with. I = imread('coins.png'); imshow(I) %% bw = imbinarize(I); bw = imfill(bw, 'holes'); imshow(bw) title('Thresholded, with holes filled') %% % The key to processing the pixels in |I| using the blobs in |bw| is to use % |regionprops| to get the |'PixelIdxList'| for each blob. s = regionprops(L, 'PixelIdxList') %% s(1) %% % |s| is a struct array. |s(k).PixelIdxList| is a vector of the linear % indices of the k-th region. You can use these values to index directly % into |I|. For example, here is the mean pixel value of the 3rd coin: idx = s(3).PixelIdxList; mean(I(idx)) %% % You can also replace object pixel values in |I| by indexing on the left % side of an assignment statement, like this: % Turn the 4th coin white and the 5th coin black: J = I; J(s(4).PixelIdxList) = 255; J(s(5).PixelIdxList) = 0; imshow(J) %% % Here's a loop that replaces the pixel values for each coin by the mean % pixel value for that coin: F = I; for k = 1:numel(s) idx = s(k).PixelIdxList; F(idx) = mean(I(idx)); end imshow(F) %% % I'll finish with a question that % : "How % can I find the location of the maximum pixel value in each labeled % region?" Here's how to find the locations and then plot them on top of % the original image. (In addition to |'PixelIdxList'|, I'll also ask % |regionprops| for |'PixelList'|, which gives the x and y coordinates of % each pixel in the region.) s = regionprops(L, 'PixelIdxList', 'PixelList'); imshow(I) hold on for k = 1:numel(s) idx = s(k).PixelIdxList; pixels_in_region_k = I(idx); [max_value, max_idx] = max(pixels_in_region_k); max_location = s(k).PixelList(max_idx, :); plot(max_location(1),max_location(2),'o','MarkerSize',10,... 'MarkerFaceColor','w','MarkerEdgeColor','k') end hold off ##### SOURCE END ##### d38778b412f54dbfbb4179ce30503ccd -->

Categories: Blogs

Our technology is haunted by demons controlled by transhuman life-forms

Cory Doctorow - 2017, September 5 - 12:24

In my latest Locus column, “Demon-Haunted World,” I propose that the Internet of Cheating Things — gadgets that try to trick us into arranging our affairs to the benefit of corporate shareholders, to our own detriment — is bringing us back to the Dark Ages, when alchemists believed that the universe rearranged itself to prevent them from knowing the divine secrets of its workings.


From Dieselgate to Wannacry to HP’s sleazy printer ink chicanery, we are increasingly colonized by demon-haunted things controlled by nonhuman life-forms (corporations) that try to trick, coerce or scare us into acting against our own best interests.

Alchemists – like all humans – are mediocre lab-technicians. Without peer reviewers around to point out the flaws in their experiments, alchemists compounded their human frailty with bad experi­mental design. As a result, an alchemist might find that the same experiment would produce a ‘‘differ­ent outcome’’ every time.

In reality, the experiments lacked sufficient con­trols. But again, in the absence of a peer reviewer, alchemists were doomed to think up their own explanations for this mysterious variability in the natural world, and doomed again to have the self-serving logic of hubris infect these explanations.

That’s how alchemists came to believe that the world was haunted, that God, or the Devil, didn’t want them to understand the world. That the world actually rearranged itself when they weren’t looking to hide its workings from them. Angels punished them for trying to fly to the Sun. Devils tricked them when they tried to know the glory of God – indeed, Marcelo Rinesi from The Institute for Ethics and Emerging Technologies called modern computer science ‘‘applied demonology.’’

In the 21st century, we have come full circle. Non-human life forms – limited liability corpo­rations – are infecting the underpinnings of our ‘‘smart’’ homes and cities with devices that obey a different physics depending on who is using them and what they believe to be true about their surroundings.

Demon-Haunted World [Cory Doctorow/Locus]

Categories: Blogs

Walkaway won the Dragon Award for Best Apocalyptic Novel

Cory Doctorow - 2017, September 5 - 12:14

Yesterday, I left the Black Rock Desert after Burning Man and my phone came to life and informed me that my novel Walkaway had been awarded DragonCon’s Dragon Award for Best Apocalyptic Novel!

I couldn’t be more pleased. My sincere thanks to all the voters who supported the novel! By the way, Tor.com published Party Discipline — a novella set in the Walkaway world — while I was away in the desert. I think it came out great.

BEST SCIENCE FICTION NOVEL:
Babylon’s Ashes by James S.A. Corey

BEST FANTASY NOVEL (INCLUDING PARANORMAL):
Monster Hunter Memoirs: Grunge by Larry Correia and John Ringo

BEST YOUNG ADULT / MIDDLE GRADE NOVEL:
The Hammer of Thor by Rick Riordan

BEST MILITARY SCIENCE FICTION OR FANTASY NOVEL:
Iron Dragoons by Richard Fox

BEST ALTERNATE HISTORY NOVEL:
Fallout: The Hot War by Harry Turtledove

BEST APOCALYPTIC NOVEL:
Walkaway by Cory Doctorow

BEST HORROR NOVEL:
The Changeling by Victor LaValle

BEST COMIC BOOK:
The Dresden Files: Dog Men by Jim Butcher, Mark Powers, Diego Galindo

BEST GRAPHIC NOVEL:
Jim Butcher’s The Dresden Files: Wild Card by Jim Butcher, Carlos Gomez

BEST SCIENCE FICTION OR FANTASY TV SERIES:
Stranger Things, Netflix

BEST SCIENCE FICTION OR FANTASY MOVIE:
Wonder Woman directed by Patty Jenkins

BEST SCIENCE FICTION OR FANTASY PC / CONSOLE GAME:
The Legend of Zelda: Breath of the Wild by Nintendo

BEST SCIENCE FICTION OR FANTASY MOBILE GAME:
Pokémon GO by Niantic

BEST SCIENCE FICTION OR FANTASY BOARD GAME:
Betrayal at House on the Hill: Widow’s Walk by Avalon Hill

BEST SCIENCE FICTION OR FANTASY MINIATURES / COLLECTIBLE CARD / ROLE-PLAYING GAME
Magic the Gathering: Eldritch Moon by Wizards of the Coast

Here are the winners of the 2017 Dragon Awards
[Andrew Liptak/The Verge]

Categories: Blogs

Party Discipline: a novella set in the world of Walkaway

Cory Doctorow - 2017, August 30 - 10:07

I wrote the novella Party Discipline while I was on my grueling US/Canada/UK tour for my novel Walkaway, last spring. Today, Tor.com publishes the tale, in which two seniors at Burbank High confront their uncertain future by planning a “Communist party” in which they take over a defunct factory and start it up again, a tangible, dangerous, playful reminder that material abundance is here, it’s just not evenly distributed.



The piece is accompanied by a gorgeous original illustration by Goñi Montes. It’s been long enough since I wrote this that I was able to re-read it with fresh eyes and found that I enjoyed it immensely, and I hope you agree.

Antoine met us at a froyo place off San Fernando, the sketchy part near the dead Ikea that had been all cut up for little market stalls that were mostly empty. I hadn’t seen him since we’d been freshmen and he’d been a senior, and in the years since he’d got strangely greyish, his skin sagging off his face and his hair shot with white, like he was an old man. He looked like he hadn’t been sleeping much, either.

He made a sign at us, a thing with his hands like the kids had done to pass messages around the classroom back when we’d been kids. It took me a second to remember what this one meant: phones down, school cop’s coming. I couldn’t figure out what that was supposed to mean, but Shirelle got it and reached into her purse and shut her phone down. Now I got it, I did the same. We’d both been infected before, of course, drive-by badware that let some creepy rando spy on us through our phones, but then we got more careful. But he wasn’t worried about randos spying through our phone: he was worried about cops.

You think Burbank PD is going to bother with you? I wanted to ask, but fact was, maybe they would. Why not. Once they bought that kind of thing, why wouldn’t they want to use it every chance they got? I probably would.

“Damn.” He looked us up and down, not like a perv, but like a grownup judging a little kid. “You two are so young. I don’t know if this was such a good idea.”

Shirelle gave him an up-and-down of her own. “Antoine, we’re only five years younger than you, fool. Smart, too. Besides, it was Lenae’s idea, not yours.”

That was news to me. Far as I knew, he’d had the idea, told Shirelle, and she’d said, Oh, Lenae said the same thing. But the way he shook his head, I knew it was true — he’d got the idea from me. That made me feel pretty badass, tell the truth.

Party Discipline [Cory Doctorow/Tor.com]

Categories: Blogs

Party Discipline: a novella set in the world of Walkaway

Cory Doctorow - 2017, August 30 - 10:07

I wrote the novella Party Discipline while I was on my grueling US/Canada/UK tour for my novel Walkaway, last spring. Today, Tor.com publishes the tale, in which two seniors at Burbank High confront their uncertain future by planning a “Communist party” in which they take over a defunct factory and start it up again, a tangible, dangerous, playful reminder that material abundance is here, it’s just not evenly distributed.



The piece is accompanied by a gorgeous original illustration by Goñi Montes. It’s been long enough since I wrote this that I was able to re-read it with fresh eyes and found that I enjoyed it immensely, and I hope you agree.

Antoine met us at a froyo place off San Fernando, the sketchy part near the dead Ikea that had been all cut up for little market stalls that were mostly empty. I hadn’t seen him since we’d been freshmen and he’d been a senior, and in the years since he’d got strangely greyish, his skin sagging off his face and his hair shot with white, like he was an old man. He looked like he hadn’t been sleeping much, either.

He made a sign at us, a thing with his hands like the kids had done to pass messages around the classroom back when we’d been kids. It took me a second to remember what this one meant: phones down, school cop’s coming. I couldn’t figure out what that was supposed to mean, but Shirelle got it and reached into her purse and shut her phone down. Now I got it, I did the same. We’d both been infected before, of course, drive-by badware that let some creepy rando spy on us through our phones, but then we got more careful. But he wasn’t worried about randos spying through our phone: he was worried about cops.

You think Burbank PD is going to bother with you? I wanted to ask, but fact was, maybe they would. Why not. Once they bought that kind of thing, why wouldn’t they want to use it every chance they got? I probably would.

“Damn.” He looked us up and down, not like a perv, but like a grownup judging a little kid. “You two are so young. I don’t know if this was such a good idea.”

Shirelle gave him an up-and-down of her own. “Antoine, we’re only five years younger than you, fool. Smart, too. Besides, it was Lenae’s idea, not yours.”

That was news to me. Far as I knew, he’d had the idea, told Shirelle, and she’d said, Oh, Lenae said the same thing. But the way he shook his head, I knew it was true — he’d got the idea from me. That made me feel pretty badass, tell the truth.

Party Discipline [Cory Doctorow/Tor.com]

Categories: Blogs

New Hair. New Shots.

Casey McKinnon - 2017, August 24 - 13:49






I got my hair cut a few months ago and was due for some new headshots, so they're finally here!

I spent months deciding on the right photographer, and I was so happy to find Eric Michael Roy of Studio Roy. When I first espied his beautiful photos, I marvelled at how he captures the eyes of his subjects and how his headshots have a theatrical quality. I feel that his images are a level up from his competition and I'm hoping these will help me level up in my career.

Categories: Blogs

See you at Burning Man!

Cory Doctorow - 2017, August 23 - 16:00

Tomorrow, I’m turning off my email and hitting the road for Burning Man, where I’ll be giving three talks, and I hope to see you there: at 4PM on Weds, Aug 20, I’m speaking at Palenque Norte at Camp Soft Landing; at noon on Thursday, Aug 31, I’ll be speaking at my home camp, Liminal Labs (6:15 and Rod’s Road); at 4:30PM on Friday, September 1, I’m speaking at the Center Camp Cafe stage. See you there — or back here after Labor Day!

Categories: Blogs

Burbank! I’ll see you tonight at 7PM at the Buena Vista library

Cory Doctorow - 2017, August 10 - 09:09

My Walkaway book-tour is basically over, but I’m taking a little victory lap tonight at my local library, the Buena Vista Branch of the Burbank Public Library. Hope to see you there!

Categories: Blogs

Walkaway is a finalist for the Dragon Awards and is #1 on Locus’s hardcover bestseller list

Cory Doctorow - 2017, August 5 - 08:26

Dragon Con’s Dragon Award ballot was just published and I’m delighted to learn that my novel Walkaway is a finalist in the “Best Apocalyptic Novel” category, along with Daniel Humphreys’ A Place Outside the Wild, Omar El Akkad’s American War, Declan Finn and Allan Yoskowitz’s Codename: Unsub, N.K. Jemisin’s The Obelisk Gate, Rick Heinz’s The Seventh Age: Dawn, and J.F. Holmes’s ZK: Falling.


I’m also delighted to note that Walkaway is currently Locus Magazine’s #1 top-selling hardcover at science fiction and fantasy bookstores in the USA and Canada.

Many thanks to all those who nominated Walkaway for the Dragon Award, and everyone who shopped for a copy at their friendly neighborhood sf store!

Categories: Blogs

A Hopeful Look At The Apocalypse: interview with Innovation Hub

Cory Doctorow - 2017, July 29 - 06:27

I’m on the latest episode of Innovation Hub (MP3):

Science-fiction is a genre that imagines the future. It doesn’t necessarily predict the future (after all, where are flying cars?), but it grapples with the technological and societal changes happening today to better understand our world and where it’s heading.

So, what does it mean when so much of our most popular science-fiction – The Handmaid’s Tale, The Walking Dead, and The Hunger Games – present bleak, depressing futures? Cory Doctorow might just have an answer. He’s a blogger, writer, activist, and author of the new book Walkaway, an optimistic disaster novel.

Three Takeaways

* Doctorow thinks that science-fiction can give people “ideas for what to do if the future turns out in different ways.” Like how William Gibson’s Neuromancer didn’t just predict the internet, it predicted the intermingling of corporations and the state.

* When you have story after story about how people turn on each other after disaster, Doctorow believes it gives us the largely false impression that people act like jerks in crises. When in fact, people usually rise to the occasion.

* With Walkaway, his “optimistic” disaster novel, Doctorow wanted to present a new narrative about resolving differences between people who are mostly on the same side.

Categories: Blogs

Hey, Little Rock, AR: there’s a special stage performance of Little Brother coming your way for Banned Books Week!

Cory Doctorow - 2017, July 27 - 13:38

Adapted by Josh Costello from the novel by Cory Doctorow
September 15, 16, 22, 23, 24, 28, 29, 30, 2017
Directed by Ryan Whitfield and Jason Green

SYNOPSIS
While skipping school and playing an alternate reality game, San Francisco teenager Marcus Yallow ends up in the middle of a terrorist attack and on the wrong side of the Department of Homeland Security. This play asks “What is the right thing to do when authorities become oppressors?”

CAST
LITTLE BROTHER CAST LIST
Marcus – Jeffrey Oakley
Ange – Kayley Shettles
Jolu – Yusuf Richardson
Daryl – Jack Clay

ENSEMBLE
Severe Haircut – Madison McMichael
Benson/Sutherland – Robert Gatlin
Guard – Essence Robinson
Mom – Isabelle Marchese
Dad – Max Green
Turk/CHP Officer – Braden Hammock
Ms. Galvez – Anais Moore
Charles – Elijah White
Police Officer 1 – Kyndall Jackson
Police Officer 2- Mia Simone Parker
Trudy Doo – Emily Shull
NPR Announcer – Allison Boggs
Concertgoer – Rachel Worthington
Reporter – Hannah Livingston
Fox Commentator – Katie Rasure
BBC Reporter – Olivia Ward
Pirate Queen – Abigail Harris
On stage light/sound/projection tech – Trenton Gorman, Claire Green

TICKETS & TIMES
$16— Adults
$12— Students & Seniors
Thursday, Friday and Saturday night curtain time is 7:30 pm.
Sunday afternoon curtain time is 2:30 pm.

The Box Office and the theater open one (1) hour prior to curtain.
The House opens 30 minutes prior to curtain.
Please arrive promptly. There will be no late admission.

Categories: Blogs

Colormap Test Image

Matlab Image processing blog - 2017, July 24 - 12:57

Today I want to tell you how and why I made these images:

After the MATLAB R2014b release, I wrote several blog posts (Part 1, Part 2, Part 3, and Part 4) about the new default colormap, parula, that was introduced in that release.

Sometime later, I came across some material by Peter Kovesi about designing perceptually uniform colormaps (or colourmaps, as Peter writes it).

I was particularly intrigued by a test image that Peter designed for the purpose of visually evaluating the perceptual characteristics of a colormap. Here is the test image:

The image is constructed by superimposing a sinusoid on a linear ramp, with the amplitude of the sinusoid getting smaller as you move away from the top row. Here are three cross-sections of the image: row 1, row 64, and row 128.

url = 'http://peterkovesi.com/projects/colourmaps/cm_MATLAB_gray256.png'; I = im2double(imread(url)); subplot(3,1,1) plot(I(1,:)) axis([1 512 0 1]) title('Row 1') subplot(3,1,2) plot(I(64,:)) axis([1 512 0 1]) title('Row 64') subplot(3,1,3) plot(I(128,:)) axis([1 512 0 1]) title('Row 128')

Here is the basic code for making this test image. I'm going to vary Kovesi's image slightly. I'll add an extra half-cycle of the sinusoid so that it reaches a peak at the right side of the image, and I'll add a full-range linear ramp section at the bottom. (If you look closely at the cross-section curves above, you'll see that the linear ramp goes from 5% to 95% of the range.)

First, compute the ramp.

num_cycles = 64.5; pixels_per_cycle = 8; A = 0.05; width = pixels_per_cycle * num_cycles + 1; height = round((width - 1) / 4); ramp = linspace(A, 1-A, width);

Next, compute the sinusoid.

k = 0:(width-1); x = -A*cos((2*pi/pixels_per_cycle) * k);

Now, vary the amplitude of the sinusoid with the square of the distance from the bottom of the image.

q = 0:(height-1); y = ((height - q) / (height - 1)).^2; I1 = (y') .* x;

Superimpose the sinusoid on the ramp.

I = I1 + ramp;

Finally, add a full-range linear ramp section to the bottom of the image.

I = [I ; repmat(linspace(0,1,width), round(height/4), 1)]; clf imshow(I) title('Colormap test image')

Last week, I posted Colormap Test Image to the File Exchange. It contains the function colormapTestImage, which does all this for you.

I = colormapTestImage;

The function has another syntax, too. If you pass it the name of a colormap, it will display the test image using that colormap. For example, here is the test image with the old MATLAB default colormap, jet.

colormapTestImage('jet')

This test image illustrates why we replaced jet as the default MATLAB colormap. I have annotated the image below to show some of the issues.

Now compare with the new default colormap, parula.

colormapTestImage('parula')

I think that illustrates what we were trying to achieve with parula: perceptual fidelity to the data.

Since I'm talking about parula, I'll finish by mentioning that we need some very subtle tweaks to parula in the R2017b release. So you can compare, I'll show you the original version that shipped with R2014b.

colormapTestImage('parula_original')

Readers, can you tell what is different? Let us know in the comments.

\n'); d.write(code_string); // Add copyright line at the bottom if specified. if (copyright.length > 0) { d.writeln(''); d.writeln('%%'); if (copyright.length > 0) { d.writeln('% _' + copyright + '_'); } } d.write('\n'); d.title = title + ' (MATLAB code)'; d.close(); } -->


Get the MATLAB code (requires JavaScript)

Published with MATLAB® R2017a

> % % After the MATLAB R2014b release, I wrote several blog posts % (, % , % , and % ) % about the new % default colormap, % , that was introduced in that release. % % Sometime later, I came across some material by Peter Kovesi about % (or colourmaps, as Peter writes % it). % % I was particularly intrigued by a test image that Peter designed for the % purpose of visually evaluating the perceptual characteristics of a % colormap. Here is the test image: % % <> % % The image is constructed by superimposing a sinusoid on a linear ramp, % with the amplitude of the sinusoid getting smaller as you move away from % the top row. Here are three cross-sections of the image: row 1, row 64, % and row 128. url = 'http://peterkovesi.com/projects/colourmaps/cm_MATLAB_gray256.png'; I = im2double(imread(url)); subplot(3,1,1) plot(I(1,:)) axis([1 512 0 1]) title('Row 1') subplot(3,1,2) plot(I(64,:)) axis([1 512 0 1]) title('Row 64') subplot(3,1,3) plot(I(128,:)) axis([1 512 0 1]) title('Row 128') %% % Here is the basic code for making this test image. I'm going to vary % Kovesi's image slightly. I'll add an extra half-cycle of the % sinusoid so that it reaches a peak at the right side of the image, and % I'll add a full-range linear ramp section at the bottom. (If you % look closely at the cross-section curves above, you'll see that the % linear ramp goes from 5% to 95% of the range.) % % First, compute the ramp. num_cycles = 64.5; pixels_per_cycle = 8; A = 0.05; width = pixels_per_cycle * num_cycles + 1; height = round((width - 1) / 4); ramp = linspace(A, 1-A, width); %% % Next, compute the sinusoid. k = 0:(width-1); x = -A*cos((2*pi/pixels_per_cycle) * k); %% % Now, vary the amplitude of the sinusoid with the square of the distance % from the bottom of the image. q = 0:(height-1); y = ((height - q) / (height - 1)).^2; I1 = (y') .* x; %% % Superimpose the sinusoid on the ramp. I = I1 + ramp; %% % Finally, add a full-range linear ramp section to the bottom of the image. I = [I ; repmat(linspace(0,1,width), round(height/4), 1)]; clf imshow(I) title('Colormap test image') %% % Last week, I posted to the File Exchange. It contains % the function |colormapTestImage|, which does all this for you. I = colormapTestImage; %% % The function has another syntax, too. If you pass it the name of a % colormap, it will display the test image using that colormap. For % example, here is the test image with the old MATLAB default colormap, % |jet|. colormapTestImage('jet') %% % This test image illustrates why we replaced |jet| as the default MATLAB % colormap. I have annotated the image below to show some of the issues. % % <> % % Now compare with the new default colormap, |parula|. colormapTestImage('parula') %% % I think that illustrates what we were trying to achieve with |parula|: % perceptual fidelity to the data. % % Since I'm talking about |parula|, I'll finish by mentioning that we need % some very subtle tweaks to |parula| in the R2017b release. So you can compare, % I'll show you the original version that shipped with R2014b. colormapTestImage('parula_original') %% % Readers, can you tell what is different? Let us know in the comments. ##### SOURCE END ##### 17a638dae0bb42cdae93c6e4992f2d18 -->

Categories: Blogs

Come see me at San Diego Comic-Con!

Cory Doctorow - 2017, July 22 - 06:14


There are three more stops on my tour for Walkaway: tomorrow at San Diego Comic-Con, next weekend at Defcon 25 in Las Vegas, and August 10th at the Burbank Public Library.


My Comic-Con day is tomorrow/Sunday, July 23: first, a 10AM signing at the Tor Books booth (#2701); then a panel, The Future is Bleak, with Annalee Newitz, Scott Westerfeld, Scott Reintgen and Alex R. Kahler; and finally a 1:15PM signing at autographic area AA06.


(Image: Gage Skidmore, CC-BY-SA)

Categories: Blogs

Jackie Returns...

Casey McKinnon - 2017, July 20 - 16:17

I'm pleased to announce that I'll be playing Jackie Kennedy again, this time in a free reading of a new play called Prince Jack. Written by Graham Barnard, and directed by Apollo Dukakis, this classical retelling of the tragic demise of president John F. Kennedy is written entirely in iambic pentameter!

Time Winters and Casey McKinnon

I'm looking forward to revisiting the role with my friend Time Winters who is playing LBJ again as well, and the talented Will Rothhaar who played an amazing Lee Harvey Oswald in Killing Kennedy. We have a great cast, and I'm so excited to be a part of it.

Details:

Prince Jack
Wednesday, August 2nd at 8pm
Studio/Stage, 520 N.Western Ave, Los Angeles, CA 90004
Tickets: Free at the door.

Categories: Blogs

Rudy Rucker on Walkaway

Cory Doctorow - 2017, July 19 - 14:39



Walkaway is my first novel for adults since 2009 and I had extremely high hopes (and not a little anxiety) for it as it entered the world, back in April. Since then, I’ve been gratified by the kind words of many of my literary heroes, from William Gibson to Bruce Sterling to the kind cover quotes from Edward Snowden, Neal Stephenson and Kim Stanley Robinson.


Today I got a most welcome treat on those lines: a review by Rudy Rucker, lavishly illustrated with some of his excellent photos. Rucker really got the novel, got excited about the parts that excited me, and you can’t really ask for better than that.

“I’m groundhog daying again, aren’t I?”

Who’s saying this? It’s the character Dis. Her body is dead, but before she died, they managed (thanks to Dis’s work) to copy or transfer the brain processes into the cloud, that is, into a network of computers. And she can run as a sim in there. And she’s having trouble getting her sim to stabilize. It keeps freaking out and crashing. And each time she restarts the character Iceweasel sits there talking to the computer sim, trying to mellow it out, and Dis will realize she’s been rebooted, or restarted like Bill Murray in that towering cinematic SF masterpiece Groundhog Day. And Cory has the antic wit to make that verb.

The first half of the book is kind of a standard good young people against evil corporate rich people thing. But then, when Dis is talking about groundhog dayhing, it kicks into another gear. Cory pulls out a different stop on the mighty SF Wurlitzer organ: the software immortality trope. As I’m fond of saying, in my 1980 novel Software, I became one of the very first authors to write about the by-now-familiar notion of the mind as software. That is, your mind is in some sense like software running on your physical body. If we could create a sufficiently rich and flexible computer, the computer might be able to emulate a person.

There’s been a zillion movies, TV shows, SF stories and novels using this idea since then. What I liked so much about Walkaway is that Cory finds a way to make this (still fairly fantastic and unlikely) idea seem real and new.

Cory Doctorow’s WALKAWAY [Rudy Rucker]

Categories: Blogs

San Diego! Come hear me read from Walkaway tomorrow night at Comickaze Liberty Station!

Cory Doctorow - 2017, July 17 - 13:19

I’m teaching the Clarion Science Fiction writing workshop at UCSD in La Jolla this week, and tomorrow night at 7PM, I’ll be reading from my novel Walkaway at Comickaze Liberty Station, 2750 Historic Decatur Rd #101, San Diego, CA 92106. Hope to see you!

Categories: Blogs

I’m profiled in the new issue of Locus Magazine

Cory Doctorow - 2017, July 17 - 06:46

Cory Doctorow: Bugging In:

‘‘Walkaway is an ‘optimistic disaster novel.’ It’s about people who, in a crisis, come together, rather than turning on each other. Its villains aren’t the people next door, who’ve secretly been waiting for civilization’s breakdown as an excuse to come and eat you, but the super-rich who are convinced that without the state and its police, the poors are coming to eat them.

‘‘In Walkaway, the economy has comprehensively broken down, and so has the planet. Climate refugees drift in huge, unstoppable numbers from place to place, seeking refuge. The world has no jobs for most people, because when robots do all the work, the forces of capital require a few foremen to boss the robots, and a few unemployed people mooching around the factory gates to threaten the supervisors with if they demand higher wages. Everyone else is surplus to requirements.

‘‘Awareness of self-deception is a tactic that’s deployed very usefully by a lot of people now. It’s at the core of things like cognitive behavioral therapy – the idea that you must become an empiricist of your emotions because your recollections of emotions are always tainted, so you have to write down your experiences and go back to see what actually happened. Do you remember the term Endless September? It’s from when AOL came on to the net, and suddenly new people were getting online all the time, who didn’t know how things worked. The onboarding process to your utopian project is always difficult. It’s a thing Burning Man is struggling with, and it’s a thing fandom is struggling with right now. We were just talking about what it’s like to go to a big media convention, a San Diego Comic-Con or something, and to what extent that’s a new culture, or it’s continuous with the old culture, or it’s preserving the best things or bringing in the worst things, or it’s overwhelming the old, or whatever. It’s a real problem, and there is a shibboleth, which is, ‘I don’t object to all these newcomers, but they’re coming in such numbers that they’re overwhelming our ability to assimilate them.’ This is what every xenophobe who voted for Brexit said, but you hear that lament in science fiction too, and you hear it even about such things as gender parity in the workplace.”

*

‘‘For me, I live by the aphorism, ‘fail better, fail faster.’ To double your success rate, triple your failure rate. What the walkaways figured out how to do is reduce the cost of failure, to make it cheaper to experiment with new ways of succeeding. One of the great bugaboos of the rationalist movement is loss aversion. There is another name for it, ‘the entitlement effect’: basically, people value something they have more than they would pay for it before they got it. How much is your IKEA furniture worth before and after you assemble it? People grossly overestimate the value of their furniture after they’ve assembled it, because having infused it with their labor and ownership, they feel an attachment to it that is not economically rational. Sunk cost is another great fallacy. You can offer somebody enough money to buy the furniture again, and pay somebody to assemble it, and they’ll turn you down, because now that they have it, they don’t want to lose it. That was the wisdom of Obama with Obamacare. He understood that Obamacare is not sustainable, that basically letting insurance companies set the price without any real limits means that the insurance companies will eventually price it out of the government’s ability to pay, but he also understood that once you give 22 million people healthcare, when the insurance companies blew it up, the people would then demand some other healthcare system be found. The idea of just going without healthcare, which was a thing that people were willing to put up with for decades, is something they’ll never go back to. Any politician who proposes that when Obamacare blows up that we replace it with nothing, as opposed to single payer – where it’s going to end up – that politician is dead in the water. ”


More…

Categories: Blogs