Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejs
titleVideoStream Protocol HandlerShow temperature video
linenumberstrue
video = ACCESS({source='Video', 
				 wrapper='GenericPush', 
				 transport='OptrisCamera', 
				 protocol='none', 
				 datahandler='Tuple',
				 schema= [
        					['image', 'IMAGEJCV'],
        					['timestamp', 'STARTTIMESTAMP'],
                            ['flagState', 'STRING']
        				 ]})
 
/// or shorter, as a source operator:
video = OPTRISCAMERA({source='Video'})
 
grayscale = MAP({expressions = [['stretchContrastCV(image, 1000, 4000, 0, 255)', 'rgb_grayscale']]}, video)
output = UDO({class='ShowImageJCV', init='0,IR Video'}, grayscale)

...

Example: Encode temperature video to video file

 

This example shows how to grab a thermal video from an optris camera and encode it into a video file. Since most video codecs operate on 24- or 32-bit RGB(A) or YUV data, the FFV1 codec (34) is used which supports 32-bit RGBA data (pixelformat pixel format 30). The 16-bit 1 channel temperature video is then reinterpreted as a 32-bit RGBA video with half of the width, where 2 16-bit pixels form one 32-bit pixel. Since fusing two pixels into one on bit level introduces jagged edges which confuse normal video encoders, it is necessary to use FFV1 since it is a lossless video compression algorithm.

 

PQL

...

 

Attention: Although the FFV1 codec writes RGBA video, the pixel format has to be set to BGRA (30)! Upon reading the video RGBA (28) can be used to retreive the original data.

PQL 

Code Block
languagejs
titleVideoStream Protocol HandlerEncode temperature video to video file
linenumberstrue
/// Grab Optris IR video stream
original = OPTRISCAMERA({source='Video'})
        				 
/// Reinterpret image: 2 16-bit pixels form one 32-bit pixel. Width halves.         				 
encoded = MAP({expressions = [['reinterpretCV(image, getWidthCV(image)/2, getHeightCV(image), 8, 4, 28)', 'image']]}, original)
 
/// Write to file
file = SENDER({sink='videofile',
	           wrapper='GenericPush',
               transport='none',
               protocol='FFmpegVideoStream',
               dataHandler='Tuple',
               options=[
							['streamUrl', 'ir.avi'],
                        ['format', 'avi'],				/// Necessary if streamUrl doesn't end with .avi, since FFmpeg can't determine the format then
    					['videoCodec', '34'],			/// FFV1
						['frameRate', '27'],			/// Optris camera operates at 27Hz
						['videoQuality', '0'],			/// Optimize Quality -> Lossless
    					['pixelformat', '30'],			/// Need to supply images in BGRA, but images get written as RGBA
						['codec:preset', 'veryslow'],	/// Best encoding -> Lossless
						['frameSizeMultiple', '2']		/// Codec requires image width and height with multiple of 2, extend image without stretching to preserve original data
                       ]}, encoded)

Example: Display encoded temperature video

This example shows how to read an RGBA-encoded temperature video, convert it back to its original 16-bit 1-channel format and display it as an RGB grayscale image.  

 

 

...

PQL 

Code Block
languagejs
titleDisplay encoded temperature video
linenumberstrue
encoded = FFMPEGVIDEO({source='Video', options=[
							['streamUrl', 'ir.avi'],
							['timeStampMode', 'filetime'],
							['useDelay', 'true'],
							['pixelFormat', '28'], /// RGBA
							['bitsPerPixel', '32']
					     ]})
        	
/// Reinterpret image: 1 32-bit pixel is extended to 2 16-bit pixels. Width doubles.         				 
original = MAP({expressions = [['reinterpretCV(image, getWidthCV(image)*2, getHeightCV(image), 16, 1, 28)', 'image']]}, encoded)        	
grayscale = MAP({expressions = [['stretchContrastCV(image, 2000, 4000, 0, 255)', 'image']]}, original)        	
        	
output = UDO({class='ShowImageJCV', init='0,IR Video'}, grayscale)