You let an operator draw freehand on a live grayscale frame — circle the defect, mark the scratch — and now you want that drawing stored in the image itself: in the archived file, the quality report, or the array your next processing step reads. The drawing is not pixels yet. It is region-of-interest data attached to the picture, and NI Vision keeps it separate from the pixel buffer until you force the two together. Here is the working sequence from drawn ROI to burned-in 8-bit pixels, the two mistakes that make the line vanish, and the checks that prove the line is in the array.
Why does the extracted plane show only the original image?
The line is missing because the drawing never reached the pixel data: an ROI drawn in a Vision Container is a contour, not pixels, so IMAQ MergeOverlay had no overlay to burn and the plane you extracted was the untouched original.
Two things break this sequence, and they fail in that order of likelihood: the ROI never became an overlay — the IMAQ ROIToMask trap, covered below — or the plane you extracted does not carry the drawing color.
Run the decisive test before changing anything else: display the image that comes out of IMAQ MergeOverlay. If the freehand line is on it, the merge worked and the problem is plane selection. If the line is not on it, nothing was merged and the fix sits upstream, at the ROI-to-overlay conversion.
One format surprise waits downstream even when the merge works: the merged image is a color image object, so code written for an 8-bit input now receives three planes. Checking the pixel format of a converted image object before the next step saves an hour of guessing.
What does the burn-in sequence need?
You need five things: the 8-bit grayscale source image, the ROI contour taken from the Vision Container, four IMAQ functions in a fixed order, a drawing color chosen before you draw, and a buffer sized for the color image the merge returns.
Every part of that list is standard equipment:
- An 8-bit grayscale source image. Mono frames from area scan cameras arrive as 8-bit grayscale by default, which is both the starting format here and the format you return to at the end. Frames exported from smart cameras behave the same once they are plain images in your development environment.
- The ROI contour from the Vision Container. Freehand, rectangle or ellipse all work; the merge consumes the contour, not a screenshot of the drawn line.
- Four functions in a fixed order: IMAQ OverlayROI → IMAQ MergeOverlay → IMAQ ExtractSingleColorPlane → IMAQ ImagetoArray.
- A deliberate drawing color. White or black makes the plane extraction independent of color choice; the arithmetic is in the plane section below.
- A downstream buffer sized for a color image. The merge returns a color image, so an array sized for the 8-bit original no longer matches.
If the camera side of the station is still unsettled, the camera finder filters by sensor, shutter and interface. And when a color camera hands you gray frames, or a mono camera arrives color, the pixel-format default at the camera is the usual cause: fixing the pixel-format default when a GigE camera shows no color image walks through it.
How do you convert a drawn ROI into pixels, step by step?
The working sequence is six steps: read the ROI from the Vision Container, attach it as an overlay with IMAQ OverlayROI, merge it with IMAQ MergeOverlay, extract the drawing color's plane with IMAQ ExtractSingleColorPlane, copy the pixels out with IMAQ ImagetoArray, and save the 8-bit result.
- Read the ROI from the Vision Container. The freehand tool leaves a contour — an ordered list of points — not pixels. Nothing in the image has changed yet.
- Attach the contour as an overlay with IMAQ OverlayROI. The overlay carries the drawing color you set. This is the step most often wired wrong; the mask trap has its own section below.
- Merge with IMAQ MergeOverlay. The merge rasterizes every attached overlay into the pixels, and the Image Dst Out is automatically converted to an RGB image: three 8-bit color planes holding the original gray values plus your line at the drawing color.
- Extract the drawing color's plane with IMAQ ExtractSingleColorPlane. The function pulls one named plane out of a color image, and the output comes back as an 8-bit grayscale image with no extra image buffer needed on this path.
- Copy the pixels out with IMAQ ImagetoArray. From here the burned line is ordinary numeric data, ready for an intensity graph or your own processing.
- Save the U8 image. A lossless format keeps the line exact; the FAQ covers the format choice.
Why does IMAQ ROIToMask fail where IMAQ OverlayROI works?
IMAQ ROIToMask returns a mask — a separate image whose values mark the region's interior — so the picture still carries no overlay and MergeOverlay burns nothing; IMAQ OverlayROI attaches the contour to the image as an overlay, which is exactly what the merge rasterizes into pixels.
The two functions sound interchangeable and are not. A mask answers "which pixels are inside the region"; an overlay is a drawing instruction tied to the image. IMAQ MergeOverlay consumes overlays. Wire the mask in instead and the merged output equals the input, the extracted plane equals the input, and the intensity graph faithfully shows an image with no line on it.
That failure is also your fastest diagnosis. When the merged image carries no drawing, stop checking the extraction and fix the conversion first.
If all you wanted was the line on screen, stop before the merge entirely: an overlay attached with IMAQ OverlayROI already displays without touching a single pixel. The display path is covered separately in overlay line thickness on a machine vision display and in showing a circular ROI overlay with a numeric radius.
Which color plane should you extract after the merge?
Extract the plane that carries the drawing color — red line, red plane; green line, green plane; blue line, blue plane — and draw the line white or black so the choice stops mattering, because white writes 255 into all three planes and black writes 0.
The arithmetic is plain RGB. A merged pixel holds one value per plane: a saturated green line is (0, 255, 0), so the red and blue planes carry 0 along the path and the original gray everywhere else. Extract red from a green drawing and the line still appears, as a dark trace; the green plane shows it at full 255. White (255, 255, 255) and black (0, 0, 0) land in every plane at the same value, which is why white or black is the practical choice for a line you intend to burn.
One limit worth planning around: on unsigned 64-bit RGB images, IMAQ ExtractSingleColorPlane supports only Red, Green or Blue as the color plane; the broader plane options belong to 32-bit RGB images.
How do you get back to U8 and prove the line is in the pixels?
IMAQ ExtractSingleColorPlane returns an 8-bit grayscale image directly — no intermediate buffer needed on this path — IMAQ ImagetoArray copies it into a numeric array, and the proof is numeric: a pixel the pen crossed reads 255 for a white line or 0 for a black line.
Worked example. On a 640 × 480 frame, draw one continuous white stroke from pixel (40, 60) to (600, 420), then extract the red plane — a white line survives there at 255.
Count the array elements equal to 255. A single continuous stroke rasterizes to at least its endpoint distance — every step along the path lays down at least one pixel — so expect roughly 666 or more, clustered on the drawn path. Three outcomes: 0 means the line never reached this plane, and you go back to the conversion step; a handful of scattered hits means you are counting the wrong value or the wrong plane; about 666 or more means the burn worked.
Run the checks in this order: look at the merged image and confirm the drawing is on it; probe one pixel you know the pen crossed and confirm 255 (or 0 for black) instead of the original gray; then run the count above.
The buffer arithmetic changes at the merge too. The 8-bit original is 640 × 480 = 307,200 bytes, and the merged image is a color image with more memory per pixel, so re-size any buffer before you read it. Reading a buffer sized for one pixel format as another is a whole class of bug — the same reason a 16-bit image buffer can hold half the expected pixels and why multi-channel buffer sizes get checked before processing. If the array view itself shows wrong values at correct coordinates, the cause is usually in how the grayscale pixels reach your code, and indexed-grayscale-pixel troubleshooting notes cover that layer.
Why does the burned line differ slightly from the drawing on screen?
The merge rasterizes the contour onto the pixel grid at merge time, so the stored line is the rasterized path: about one pixel wide, in the exact drawing color, and close to — but not identical with — the smoothed line the display renders from the overlay.
That difference is expected, not a defect. Before the merge, the overlay is a drawing instruction the display renders fresh each frame; after the merge, the line is fixed pixel values. Curves quantize to neighboring pixels and joints snap to the grid, which is why a merged freehand stroke comes back similar, but not identical, to the drawing you saw.
The consequence for your data: do not measure geometry from the burned pixels if the exact contour matters downstream. Keep the ROI data alongside the image — the burned line is proof for people, the contour is the truth for algorithms.
When should you not burn the annotation into the image?
Keep annotations off the pixels whenever the same frame still feeds measurement, thresholding or a model: the burned line changes those pixel values, so histograms, particle analysis and inspection results shift. Burn only the copy you archive, display or attach to a report.
The pattern that avoids the conflict uses two copies of every annotated frame. The display copy carries overlays, which never touch pixels — the text overlay that leaves the live frame unaltered works the same way — while the processing copy stays clean and only the archive copy gets the burn.
Units matter here as well: a burned line is pixels, not millimetres. Converting its length needs a calibration from your optics — a target imaged at the working distance — not from the image's DPI metadata, which describes screens and printers; calibrating pixels to millimetres from image DPI alone is the shortcut that question keeps attracting.
Where this leaves you: ROI → IMAQ OverlayROI → IMAQ MergeOverlay → IMAQ ExtractSingleColorPlane → IMAQ ImagetoArray, with a white or black line and a pixel count near the stroke length reading 255 or 0. If the camera feeding that pipeline is still an open decision, the camera configurator narrows the choice by sensor, shutter and interface, and the neighboring fixes for buffers, formats and displays live on the machine vision systems topic page. If you would rather talk a station through with someone, the contact page is the way in.
Questions
Can the annotation be burned in without the image ever becoming RGB?
Not through the merge route: IMAQ MergeOverlay converts the destination to an RGB image by design, and the single-plane picture returns only through the color-plane extraction. To stay 8-bit throughout, skip overlays and rasterize the path yourself — interpolate the drawn points (a spline at an interpolation factor of 10 fills the gaps fast pen moves leave) and write the drawing value into those array positions.
How do you burn two different annotations into one image and separate them again?
Draw each in a different saturated primary color, for example red for the measurement line and green for the defect mark. After the merge, IMAQ ExtractSingleColorPlane returns one image per color: the red plane carries the original gray background with the red line at 255, the green plane the same background with the green marks, so each annotation comes back on its own copy.
Which file format keeps the burned-in line intact?
A lossless one. PNG and BMP store every pixel value exactly, so the line you burned is the line you get back. JPEG discards detail to shrink the file and can soften or shift a single-pixel line; if a downstream tool only accepts JPEG, burn the line, save losslessly first, and convert at the last step.
How do you make the burned line thicker than one pixel?
The merge writes the rasterized contour, which runs about a pixel wide. Two options: draw the stroke several times with a small offset so the passes overlap, or dilate the extracted line after the plane extraction — a 3 × 3 dilation widens the trace to about three pixels while the background stays untouched.
Does this work on a color image, or only on grayscale?
It works on both, and color is simpler: merge the overlay and stay in RGB, extracting a plane only if your next step needs single-plane data. The grayscale route exists because your source and destination are 8-bit; if a mono camera hands you color frames anyway, fix the camera's pixel-format default before adding this step.