.
Here comes the basic example of writing an image to your hard-disk. As an example, we generate a single-channel gray-ramp image of size 512x512 named ImageGrayRamp
and write it to disk using the PNG format:
* Save a single image to C:\TEMP in format PNG gen_image_gray_ramp (ImageGrayRamp, 1, 1, 128, 256, 256, 512, 512) write_image (ImageGrayRamp, 'png', 0,'C:/TEMP/testimage.png')
The file format is specified in the parameter Format
of the operator write_image
. Normally, we recommend saving images in a lossless image format. Ideally, the file format should be able to save all of HALCON's image data. The file format should be readable for 3rd-party applications for quick overviews e.g. in Windows Explorer. Saving should be reasonable fast while compressing (without information loss!) as good as possible. Therefore we recommend saving images in PNG format, i.e. with Format
set to 'png'
. PNG can save 1-channel images and 3-channel images (color images) and can also save the image domain (ROI) as alpha channel. TIFF would be possible, too, but the format seems a bit uncommon nowadays and BMP is uncompressed and seems a bit Windows specific.
On the other hand, lossy image formats like JPG can save a lot of disk space, but at the cost of introducing artifacts into the image. In the following example you can see artifacts which were added when saving the image of a circle with the write_image option jpeg 20
: In addition to the edge of the circle a few additional detected (unwanted!) edges appear in the right image (the image with the JPEG artifacts).
The image formats hobj
and ima
are HALCON-specific. The file format hobj
is best to save images with all information available but it is not recognized by any 3rd-party application and therefore is a bit cumbersome to manage e.g. with Windows Explorer. I'd recommend using hobj
if you have special images with more than three channels or with an image type other than byte
(e.g. uint2
). ima
is the legacy format of HALCON to save images. It generates two files, one with the extension .ima
and one with the extension .exp
which contains additional metadata (for example, size and format of the image).
To select the right image file format for archiving images is very important. The following table tries to help in choosing the right format. The table rows are sorted with the (in our opinion) best image file formats for machine vision coming first, but this of course depends on your specific needs:
Format | Lossless | channels | domain | types | multiple objects | generally recognized1 |
---|---|---|---|---|---|---|
'png' | 1, 3 | byte , uint2 | ||||
'tiff' | any | byte ,uint2 ,real ,... | ||||
'hobj' | any | any | ||||
'bmp' | 1, 3 | byte | ||||
'jpeg' | 1, 3 | byte | ||||
'jp2' (JPG-2000) | , | any | byte , uint2 | |||
'jpegxr' 2 | , | any | byte ,uint2 ,real ,... | 3 | ||
'ima' | 1 | any4 |
.jxr
FileName
complex
and vector_field
The parameter FillColor
can be left at the default value of 0. In almost 10 years of using HALCON I never had to change this default of operator write_image
. The parameter FileName
can contain the file name only to save the image in the current directory. If no extension is given, the extension corresponding to the Format
is automatically added to the file name. If an absolute path is specified, you have to use forward slashes, even on Windows. A few examples are:
* Save PNG in current directory. The following two lines * produce the same output file testimage.png write_image (ImageGrayRamp, 'png', 0,'testimage.png') write_image (ImageGrayRamp, 'png', 0,'testimage') * Save image file 'testimage.tif' in TIFF format in directory C:\TEMP write_image (ImageGrayRamp, 'tiff', 0,'C:/TEMP/testimage') * PNG file format can also save the domain of a HALCON image: gen_circle (Circle, 200, 200, 100.5) reduce_domain (ImageGrayRamp, Circle, ImageReduced) write_image (ImageReduced, 'png', 0, 'C:/TEMP/image_reduced.png')
* Example code to acquire images from the first DirectShow device (a Webcam?) AcqName := 'DirectShow' info_framegrabber(AcqName,'device',__,Devices) gen_empty_obj (ImagesCaptured) for Index := 0 to 29 by 1 grab_image (Image, AcqHandle) * append current Image to ImagesCaptured concat_obj (ImagesCaptured, Image, ImagesCaptured) endfor * Example code to write multiple images stored in ImagesCaptured * to separate files 'image000', 'image001', ... TargetDir := 'C:/TEMP' count_obj (ImagesCaptured, NumberImages) for Index0 := 0 to NumberImages-1 by 1 select_obj (ImagesCaptured, CurrentImage, Index0+1) * The $'.3' makes sure that the numbers always consist of 3 digits. * Leading zeros are prepended as needed. This leads to better sorting of the * files: * good: sorted 'image000', 'image002', 'image003', 'image004', ... * bad: sorted 'image0', 'image1', 'image10', 'image2', 'image3', ... write_image (CurrentImage, 'png', 0, TargetDir + '/image_' + Index0$'.3') endfor
As of HALCON 13, the operator write_image
is not parallelized, which means that it can take a very long time if you want to write many images, e.g. a stream of images from an acquisition device. The following snippet parallelizes write_image
manually. On my CPU (4 cores, 8 threads) and a SSD drive as write target this reduces the time needed to write 30 color images of size 1920x1080 from 35 seconds (sequential) to 6 seconds (parallel):
* Example code to write multiple images stored in ImagesCaptured * to separate files 'image000', 'image001', ... Parallel version. count_obj (ImagesCaptured, NumberImages) get_system ('processor_num', ProcessorNum) for IndexSingle0Chunk := 0 to NumberImages-1 by ProcessorNum ThreadIDs := {} for IndexSingle0 := IndexSingle0Chunk to min2(NumberImages-1,IndexSingle0Chunk + ProcessorNum - 1) by 1 select_obj (ImagesCaptured, CurrentImage, IndexSingle0+1) par_start<ThreadIDs.at(IndexSingle0-IndexSingle0Chunk)> : write_image (CurrentImage, 'png', 0, TargetDir + '/image_' + IndexSingle0$'.3') endfor convert_vector_to_tuple (ThreadIDs, ThreadIDsTuple) par_join(ThreadIDsTuple) endfor
write_image
with Format
'hobj'
the operator write_object
can be used:
write_object (Images, TargetDir + '/myobjects')
The extension hobj
is automatically added to the filename. Use this for example if you want to access the saved images with HALCON only.
* Save images to disk in HALCON's serialized data stream format open_file (TargetDir + '/myserialized.dat', 'output_binary', FileHandle) * serialize_image (Images, SerializedItemHandle) serialize_object (Images, SerializedItemHandle) fwrite_serialized_item (FileHandle,SerializedItemHandle) close_file (FileHandle) * Read images from disk in HALCON's serialized data stream format open_file (TargetDir + '/myserialized.dat', 'input_binary', FileHandle) fread_serialized_item (FileHandle, SerializedItemHandle) * deserialize_image (ImagesRead, SerializedItemHandle) deserialize_object (ImagesRead, SerializedItemHandle) close_file (FileHandle)
Although the task to write images to disk and archive them for later usage sounds like a simple job at first, it can be a surprisingly complex topic. We hope to have clarified the various possibilities a bit. Please contact us if you have any questions or need help with your project.