Linear Filtering of Images on The TI C62XX/C67XX (Image Processing) Part 1

C6701 EVM image filtering programs may be found on the CD-ROM under the directory Chap4\LinearFilter\C62xxC67xx.As a consequence, neither the input image buffer nor the output image buffer fits in internal on-chip RAM, a situation that if not dealt with appropriately has deleterious effects on the efficiency of the code. Thus the implementations presented in this topic serve two purposes; one, to provide tested code that implements 2D convolution and two, to illustrate strategies for handling the situation where data does not fit in the DSP internal RAM. All of these programs are fixed-point implementations, using a Q15 data format.

The image dimensions, 16-bit short integer input buffer in_img, and kernel size NH are defined in the header file image.h, which is shared amongst all of the programs in the C62xxC67xx directory. The in_img buffer is initialized with pixel data from the ubiquitous "Lenna" image, which is used as a test image in many image-processing texts. Of course, alternate data can be fed into the in_img array if so desired.The size of the kernel may also be changed by adjusting the definition of NH, however NH must be odd. The description of the code often makes reference to the half-width of the kernel, and this parameter is referenced in the code by the BOUNDARY preprocessor symbol.

IMG_cor r_gen in action. This diagram depicts two iterations of the 2D image filtering algorithm in f ilter imglib . c. Labels in bold, courier font refer to actual variables in the implementation. A series of ID FIR filtering operations is performed on each scan-line of in img, and then these ID results are combined via a summation in the other direction and placed in out_img. This process continues as we march down in_img.


Figure 4-9. IMG_cor r_gen in action. This diagram depicts two iterations of the 2D image filtering algorithm in f ilter imglib . c. Labels in bold, courier font refer to actual variables in the implementation. A series of ID FIR filtering operations is performed on each scan-line of in img, and then these ID results are combined via a summation in the other direction and placed in out_img. This process continues as we march down in_img.

The linker command file image_filter.cmd is shared amongst the various C62xx/C67xx programs. It is identical to the linker command files used in the CCStudio projects for next topic, except that the ".cinit" section (the portion of the memory map reserved for constants and other data for the initialization of global C variables) is now mapped to external RAM (SBSRAM) instead of internal RAM. This is necessary if the 64k (256×256) element array in_img is to be pre-initialized with pixel data, as the initialization data will not fit in DSP internal RAM.

Finally, there is another shared source file, vecs . asm, used for some of the later implementations presented in this section. This file contains the vector interrupt table and will be explained in more detail when Direct Memory Access (DMA) is introduced.

2D Filtering Using the IMGLIB Library (filter_imglib)

A program set up to use the IMGLIB 2D filtering function IMG_corr_gen can be located in the filter_imglib subdirectory. IMG_corr_gen can be used to implement a generalized 2D filtering process by repeatedly invoking it for every sliding window position down the rows of an image, each time passing into the function the current row of the mask and the current row of the image6. This in effect ends up passing rows of in_img through the ID FIR filter given by the i"’ row of mask. NH filtered rows are then combined via summation across the orthogonal (column-wise) direction, thereby producing pixels in the output image that have been filtered in a 2D fashion. This process is illustrated in Figure 4-9 for the case of a 3×3 kernel (NH=3).

Listing 4-1 is the contents of f ilter_imglib. c. Note that this and all other programs set the first and last kernel half-width columns and rows to zero. Thus if the C preprocessor symbol NH is 5, the first and last two rows and columns of out_img are set to zero.

Listing 4-1: filter imglib.c

Listing 4-1: filter imglib.c

 

 

 

 

Listing 4-1: filter imglib.c

 

 

 

 

Listing 4-1: filter imglib.c

 

 

 

 

 

Listing 4-1: filter imglib.c

Unfortunately, as of version 1.02 of the C62x/C67x IMGLIB, IMG_corr_gen does not work as advertised! Most of the TI library reference manuals contain "behavioral C code" translations of their documented functions. Since the functions are more often than not written in hand-optimized assembly code, this behavioral C code (which can usually also be found in the relevant algorithm header file) can be invaluable when attempting to understand exactly what an algorithm is intended to accomplish. In this program, a local function corrgen has been defined which is basically the behavioral C code for IMG_corr_gen copied and pasted from img_corr_gen. h into f ilter_imglib. c. This function does work, but serves the purpose of providing a completely unoptimized (aside from using fixed-point arithmetic) implementation of image filtering. The corr gen function in f ilter imglib. c does not handle saturation correctly, and there are numerous inefficiencies in the loop, many of which could be tackled by using special features of the TI C compiler and/or rewriting the loop in linear assembly. Using the profiling technique described in 3.4.3, this implementation takes an average of 46,972,076 cycles to filter a 256×256 image with a 5×5 kernel, with no debug symbols and the -o3 compiler option selected. The fact that memory usage, specifically the cost incurred by accessing pixels stored in external RAM, is not optimized at all in this program contributes greatly to the cycle count – a solution to this issue will be presented in subsequent image filtering programs. Incidentally, using IMG_corr_gen instead of the locally defined corr_gen yields an average cycle count of 10,775,445 cycles, for a speedup of over 4x. However it is difficult to draw any clear conclusions from this measurement as the output is incorrect. In the next section we shall see how an alternative function from the DSPLIB library that works can be used as a replacement for IMG_corr_gen.

Code Composer Studio provides numerous data visualization tools. In fact, it is such a powerful development environment that it even offers the ability to render buffers as images, a feature that is obviously of great utility when developing image processing applications. To use this feature, build the filter imglib program with debug symbols enabled and set a breakpoint in main sometime after the call to f ilter_image. Then run the program, and when the debugger stops at the breakpoint, select the View|Graph|Image menu item. This brings up a dialog that configures how to render the data in an image buffer. There is no monochrome color space option, so to display gray-scale images, select the RGB color space option and point the R, G, and B channels to the same buffer (in this case out_img). Figure 4-10 is a CCStudio screen-shot showing the output of the low-pass filtered Lenna image, after passing it through an averaging 5×5 kernel. The image visualization feature of CCStudio is quite full-featured, in fact if you click within the image window the pixel coordinates and the intensity is displayed in the status bar at the bottom of the display. MATLAB provides similar functionality through its pixval command.

Next post:

Previous post: