HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

Implementation of MATLAB's `im2col`

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementationim2colmatlab

Problem

The function im2col in MATLAB is very useful to vectorize Patch based Image Processing algorithms. The problem is the function isn't optimized and doesn't use C Code. I'm trying to build efficient C code for that.

This is the code I created:

```
function [ mColumnImage ] = ImageToColumns( mInputImage, blockRadius )
% ----------------------------------------------------------------------------------------------- %
% [ mColumnImage ] = ImageToColumns( mInputImage, blockRadius )
% Creates an column image from the sliding neighborhood in mInpuImage
% Input:
% - mInputImage - Input image.
% Matrix, 1 Channels, Floating Point
% - blockRadius - Local Window Radius.
% Scalar, Floating Point, {1, 2, ..., inf}.
% Output:
% - mColumnImage - Input image.
% Matrix, 1 Channels, Floating Point, [0, 1]
% Remarks:
% 1. Prefixes:
% - 'm' - Matrix.
% - 'v' - Vector.
% 2. C
% TODO:
% 1. I
% Release Notes:
% - 1.0.000 22/08/2014 R
% * First release version.
% ----------------------------------------------------------------------------------------------- %

numRows = size(mInputImage, 1);
numCols = size(mInputImage, 2);

blockSize = (2 * blockRadius) + 1;

numPixelsToProcess = (numRows - blockSize + 1) * (numCols - blockSize + 1);

mColumnImage = zeros((blockSize * blockSize), numPixelsToProcess);

colImageColIdx = 0;

for iColIdx = (blockRadius + 1):(numCols - blockRadius)
for jRowIdx = (blockRadius + 1):(numRows - blockRadius)
colImageColIdx = colImageColIdx + 1;
colImageRowIdx = 0;
for kPixelColIdx = -blockRadius:blockRadius
for lPixelRowIdx = -blockRadius:blockRadius
colImageRowIdx = colImageRowIdx + 1;
mColumnImage(colImageRowIdx, colImageColIdx) = mInputImage((jRowIdx + lPixelRowIdx), (iColIdx + kPixelColIdx));
end

Solution

This is a valid C code which implements the above:

void ImageToColumns(float* mO, float* mI, int numRows, int numCols, int blockRadius)
{
    int blockSize, blockNumElements, colImageColIdx, colImageRowIdx;
    int ii, jj, kk, ll;

    blockSize           = (2 * blockRadius) + 1;
    blockNumElements    = blockSize * blockSize;
    colImageRowIdx      = -1;

    for (ii = blockRadius; ii < (numRows - blockRadius); ii++)
    {
        for (jj = blockRadius; jj < (numCols - blockRadius); jj++)
        {
            colImageRowIdx = colImageRowIdx + 1;
            colImageColIdx = -1;

            for (kk = -blockRadius; kk <= blockRadius; kk++)
            {
                for (ll = -blockRadius; ll <= blockRadius; ll++)
                {
                    colImageColIdx = colImageColIdx + 1;
                    mO[(colImageRowIdx * blockNumElements) + colImageColIdx] = mI[((ii + kk) * numCols) + jj + ll];
                }

            }
        }
    }

}


Clearly this a memory bounded algorithm.

Code Snippets

void ImageToColumns(float* mO, float* mI, int numRows, int numCols, int blockRadius)
{
    int blockSize, blockNumElements, colImageColIdx, colImageRowIdx;
    int ii, jj, kk, ll;

    blockSize           = (2 * blockRadius) + 1;
    blockNumElements    = blockSize * blockSize;
    colImageRowIdx      = -1;

    for (ii = blockRadius; ii < (numRows - blockRadius); ii++)
    {
        for (jj = blockRadius; jj < (numCols - blockRadius); jj++)
        {
            colImageRowIdx = colImageRowIdx + 1;
            colImageColIdx = -1;

            for (kk = -blockRadius; kk <= blockRadius; kk++)
            {
                for (ll = -blockRadius; ll <= blockRadius; ll++)
                {
                    colImageColIdx = colImageColIdx + 1;
                    mO[(colImageRowIdx * blockNumElements) + colImageColIdx] = mI[((ii + kk) * numCols) + jj + ll];
                }

            }
        }
    }


}

Context

StackExchange Code Review Q#61448, answer score: 2

Revisions (0)

No revisions yet.