Pixel Grid Update
As it turns out, there are several ways to draw thousands of line segments with just one "line" object.
Today's post describes recent updates to Pixel Grid, one of my File Exchange submissions. I have previously written about Pixel Grid in my 17-Feb-2011 and 13-Jun-2019 MATLAB Central blog posts.
Pixel Grid is meant to subtly outline the pixel edges when an image is displayed so that the pixels are very big on the screen. Here is an example.
bw = [...
0 0 0 1 0 0 0
0 0 1 0 1 0 0
0 1 0 0 0 1 0
1 1 1 1 1 1 1 ];
imshow(bw, 'InitialMagnification', 'fit')
(How many rows are in the image displayed above?)
pixelgrid
Before I describe the updates, I'd like to recap the key implementation techniques involved.
Drawing Many Line Segments Efficiently
If an image has thousands of rows and columns, then drawing a complete pixel grid requires thousands of line segments. The MATLAB graphics system can draw all those line segments much faster if we can somehow minimize the creation of graphics line
objects. As it turns out, there are several ways to draw all the line segments with just one line
object. My preferred method is to draw N + 1 vertical line segments and M + 1 horizontal line segments (for an MxN image matrix), with the segment vertices separated by NaN
values in the XData
and YData
properties.
To illustrate the technique, consider an image with 10 rows and 15 columns. Here is one way to draw the entire grid with a single line
object. First, construct vectors of x and y vertices for the vertical line segments, with the segments separated by NaN
values.
M = 5;
N = 10;
xv = (0:N) + 0.5;
xv = [xv ; xv ; NaN(1,N+1)];
xv = xv(:);
yv = [0.5 ; M+0.5 ; NaN];
yv = repmat(yv,1,N+1);
yv = yv(:);
Drawing what we have so far:
plot(xv,yv)
axis equal
axis ij
axis padded
Now construct arrays containing vertices for the horizontal line segments.
xh = [0.5 ; N+0.5 ; NaN];
xh = repmat(xh,1,M+1);
xh = xh(:);
yh = (0:M) + 0.5;
yh = [yh ; yh ; NaN(1,M+1)];
yh = yh(:);
Here's what the horizontal line segments look like:
plot(xh,yh)
axis equal
axis ij
axis padded
The horizontal and vertical line segment vectors can be combined and then drawn together:
x = [xh ; xv];
y = [yh ; yv];
plot(x,y)
axis equal
axis ij
axis padded
## Guaranteeing Grid Visibility
Consider again the first image shown above:
imshow(bw, 'InitialMagnification', 'fit')
How can we draw pixel grid lines so they will always be visible, no matter what the image pixel color is underneath?
Fundamentally, the answer is to draw the line using two contrasting colors. With MATLAB graphics, two techniques come to mind:
- Draw a thick line with one color, and then draw a thin line on top of it using a contrasting color
- Draw one a solid line with one color, and then a dashed line on top of it using a contrasting color
Here is the first technique:
plot(x,y, Color = "black", LineWidth = 3)
hold on
plot(x,y, Color = "white", LineWidth = 1)
hold off
axis equal
axis ij
axis padded
And here is the second:
plot(x,y, Color = "black", LineWidth = 1, LineStyle = "-")
hold on
plot(x,y, Color = "white", LineWidth = 1, LineStyle = "--")
hold off
axis equal
axis ij
axis padded
For Pixel Grid, I wanted to keep the grid visible but subtle, so I have used the second technique with thin lines and different shades of gray.
imshow(bw, 'InitialMagnification', 'fit')
pixelgrid
## Pixel Grid Update: Automatic Visibility Control
It only makes sense to create and display a pixel grid of the image pixels are very large on the screen. At a typical magnification level, a visible pixel grid would completely obscure the image. Previous versions of Pixel Grid left it to the user to know when it makes sense for the pixel grid to be created and to be visible.
With the latest Pixel Grid update, you can add it to any image, and the grid will automatically stay invisible until you zoom in far enough to make the individual pixels big.
A = imread("roses.jpg");
imshow(A)
pixelgrid
In the image displayed above, the pixel grid has been added but is not visible. If you zoom in far enough, the grid becomes visible automatically:
zoomImage(100)
And when you zoom back out a bit, the pixel grid automatically becomes invisible again.
zoomImage(0.5)
The automatic visibility control is implemented using the MarkedClean
event, as described on Yair Altman’s 27-May-2015 blog post, “Undocumented HG2 graphics events”.
Automatic visibility control also uses my recent File Exchange submission, “Image Zoom Level and Pan Utilities”, to determine the approximate physical size of image pixels on the display. This submission also contains the zoomImage
function used above.
Wrap-Up
Pixel Grid has been around for a while on the File Exchange, but there is a recent update on the File Exchange that makes it more convenient to use.
If you use Pixel Grid in your own work with MATLAB, I’d be interested to know your thoughts about it. To send me questions or comments about this post, or about other posts, choose “Contact” from the navigation menu.