Posts Tagged ‘foss’

Convert your MP3 bitrates via terminal

November 8, 2010 1 comment

Image courtesy of technabob.

I just had my machine reformatted for a new Ubuntu version and I spent hours the other night reorganizing my files.  I realized that among the ones taking up most of my disk space are my MP3 files.

MP3 is a lossy audio compression scheme, but you can actually take the option to reduce its bitrate (say for your small capacity MP3 player) without losing much of the quality.  Some music files are at 320kbps, but the standard rate is 128kbps.  You will realize that a file has a high bitrate if the size is too large for the song length.

You can calculate the size of an MP3 file using this:

z = (x * y) / 8

x = length of song (in seconds)
y = bitrate (in kilobits per second)
z = resultant file size (in kilobytes) – dividing by 8 gives the result in bytes

So let’s say you have an MP3 of length 3 minutes = 180 seconds.  At 128kbps, your file will be as big as:

z = (180*128)/8 = 2880kb = 2.880Mb

Compared to when you have it at 320kbps:

z = (180*320)/8 = 7200kb = 7.200Mb

Now that’s significant difference when you have thousands of MP3s in your disk.  Most people take the option to convert their MP3 files using a software (e.g. SoundConverter, another FOSS app).  But if you would like to keep things light on your machine, you would wish instead to install the library LAME (a recursive acronym meaning LAME Ain’t an MP3 Encoder).  For more information on this package, run: man lame.

So how does it work? To do the bitrate conversion, run on the terminal (as root):

 lame --mp3input -b <bitrate> <file.mp3> <destination.mp3> 

where the bitrate could range from 8 – 320, depending on your need.

If you have more than a handful of MP3 files, you can automate the conversion using the following shell script:

 for f in *.mp3 ; do lame --mp3input -b <bitrate> "$f" <path_to_destination>/"$f" ; done 

Note that leaving the destination parameter as null saves the file in the form file.mp3.mp3 while setting this parameter to your player’s location causes your file to land there.

[1] Wikipedia, 2010. MP3.
[2] Jhollington, 2004. kbps ?. iLounge Forums.
[3] Ubuntu Packages, 2010. Package: lame.
[4] Ubuntu Development Team, 2010. “lame” package. Launchpad.
[5] Vanadium, 2007. Convert MP3 bitrate. Ubuntu Forums.


5. Image Enhancement by Histogram Manipulation

July 6, 2010 4 comments

An image histogram is a representation of the frequency distribution of values in an image.  It plots the number of pixels there are containing particular tonal values.  Photographers oftentimes use histogram manipulation in order to restore the proper contrast of the images or simply depict a particular mood on the scenery.

If Px(i) is the image histogram for pixel value i, the cumulative distribution function (or CDF) for all pixel values is expressed as

Images are easily modified and best manipulated using cumulative frequencies.  Backprojection is referred to as the method of manipulating an image’s CDF to conform a desired distribution.  This is performed by tracing back the frequency of a particular pixel tone towards the desired CDF and then replace it with its new corresponding value.

Figure 1. Image histogram manipulation by means of backprojection.

For instance we have the image below as an example of a poor-contrast image, with its image histogram and CDF shown on the attached plots.

Figure 2. An example of a dark photograph (in grayscale). Courtesy of M. Beslac.

Using Scilab and the SIVP toolbox, we can improve the image by implementing histogram manipulation through the backprojection algorithm.  First, we use the built-in function imhist() to obtain the image histogram from the grayscale image.  We used plot2d3() to allow us to plot our data in vertical bars.

I = imread('fakefree.jpg');
J = rgb2gray(I);

[counts, cells] = imhist(J);      // defaults to 256 bins
scf(0); plot2d3(cells, counts, rect=[0,0, 256, max(counts)]);
 // rect=[xmin, ymin, xmax, ymax]

We then utilize the function cumsum(), which returns an array corresponding to the cumulative distribution. Note that in our implementation we perform a normalization for the CDF.

cumulative_sum = cumsum(counts);
cumsum_max = max(cumulative_sum);
cdf = cumulative_sum/cumsum_max;  // normalized cumsum

scf(1); plot2d(cells, cdf, rect=[0, 0, 256, max(cdf)]);

For better coding practices, we create a self-defined function to solve for the x-values of the traced frequencies on our CDF plot. If for instance we desire to imitate a linear function obeying the equation y = (1/255)*x, we design our function to do an inverse of this relation. (This code snippet of the function may be placed at the beginning of the code or in a separate file.)

function inv_linearCDF = invLinearCDF(y)
  y = y*255;                          // denormalization
  inv_linearCDF = round(y);           // linear_cdf = (1/255)*x

Note that we performed denormalization on the CDF in order to work with actual values, and used the function round() for discrete approximations.  Next, we create a second image matrix – a copy of the original – where we will later apply the changes due to our manipulation. Iterating towards each pixel value, we retrace the individual frequencies and replace them with new pixel values on the second image.

K = J;      // a copy of the original image

for i = 1:256
  new_x = invLinearCDF(cdf(i));
  K (find(J==i-1)) = new_x;    // i-1 referring to pixel values (range:0-255)

Below is the new image now approximately conforming to the linear distribution.

Figure 3. Histogram manipulated image via backprojection towards a linear CDF.

We can perform the same method with non-linear distributions such as the parabolic function, implemented similar to the one below.

function inv_parabolicCDF = invParabolicCDF(y)
  y = y*255^2;                         // denormalization
  inv_parabolicCDF = round(sqrt(y));   // parabolic_cdf(x) = x^2

We may also apply this with a logarithmic function:

function inv_logarithmicCDF = invLogarithmicCDF(y)
  y = y*log(255);                      // denormalization
  inv_logarithmicCDF = round(exp(y));  // logarithmic_cdf(x) = log(x)

The following are the image results of the previous two non-linear functions, including their manipulated histograms and cumulative frequencies. We can observe how the images are similar to an overexposed and underexposed image.

Figure 4. Image backprojected towards (1) a parabolic CDF; (2) a logarithmic CDF.

Photographers usually use image processing softwares to easily perform histogram manipulation on photographs. GIMP or the GNU Image Manipulation Program (a FOSS graphics editor), offers this capability via graphical interface.  To navigate to this function, go to Colors > Curves.  Make sure the image is initial set to grayscale by choosing Image > Mode > Grayscale.  Here is a snapshot of an actual curve manipulation on GIMP.

Figure 5. Desktop snapshot of GIMP running the curve manipulation feature.

Now, being able to adjust images via histogram manipulation, we can achieve improved images with better brightness and color contrast.

For this segment, I would rate myself 11 for understanding the important ideas and, in addition, for exploring a software that applies the image enhancement method.

[1] Esporlas, C., 2009. Histogram backprojection. Applied Physics 186.
[2] Photoxels, 2010. Digital photography tutorial: Histogram.
[3] Soriano, M., 2010. Image enhancement by histogram manipulation. Applied Physics 186.
[4] Wikipedia, 2010. Histogram equalization.
[5] Wikipedia, 2010. Image histogram.

2. SciLab Basics

June 22, 2010 Leave a comment

For the rest of the semester, I’d probably be using a couple of essential tools on my journey to learning image processing. One brilliant software I encountered is SciLab, an high-level cross-platform programming language very efficient for numerical computations and scientific visualizations. Many researchers choose SciLab for its vast capabilities on signal processing and image enhancement. Best of all, unlike other software, SciLab is non-proprietary and completely open-source. The product is in the public domain – freely downloadable online. Anyone can run, copy, modify and redistribute its packages. For the download location, click here.

SciLab offers a good Integrated Development Environment (IDE) for the user for working with codes and figures. The following is a screenshot I have captured from my own desktop.

Figure 1. A snapshot of the SciLab IDE

The tool offers a console for easy preview of short one-liner codes, and an embedded test editor, called SciPad, for working with files.

My primary operating system is Linux (specializing in GNU-based applications).  Currently I am using the Ubuntu distribution.  For installing SciLab in Ubuntu, one can open the package list at:

System > Administration > Synaptic Package Manager

then mark SciLab* for installation.

Alternatively, simply open the terminal and enter (as root):

sudo apt-get install scilab

The image processing end of the software is referred as the SciLab Image and Video Processing Toolbox (SIVP), an equivalent of the SIP in Windows.  To install this extension, run:

sudo apt-get install sivp

This tool can be loaded from the SciLab console via:

Toolboxes > sivp

*Latest stable version as of article date: SciLab 5.2.1-8, compatible with SIVP 0.5.0-1.

For a good jumpstart, I used SciLab scripts to familiarize with the basic functionalities (and workarounds) of the imaging tool.  On a 2D canvass, I constructed basic shapes using binary matrices.  The initial scipt [1] reads:

nx = 500; ny = 500;      // defines the number of elements along x and y
x = linspace(-1, 1, nx); //defines the range
y = linspace(-1, 1, ny);
[X, Y] = ndgrid(x, y);   // creates two 2-D arrays of x and y coordinates
A = zeros(nx, ny);

This basically prepares a 500×500 matrix filled with zeroes (ready to be filled with data later).  The script to create a circle will be:

r = sqrt(X.^2 + Y.^2);   // element-per-element squaring of X and Y
A (find((r&lt;0.7))) = 1;  // values of r where r&lt;0.7

Modifying this code creates an annulus:

A (find((r &lt; 0.7) &amp; (r &gt; 0.4))) = 1; // values of r where  0.4&lt;r&lt;0.7

To view the figure, insert:

imshow(A);    // displays the 2D matrix A

Load the program into the console via:

Execute > Load into SciLab

or simply, Ctrl+L.  Figure 2A shows the output figure of the set of code.

Figure 2. A. annulus, B. square

In order to produce the square image (Figure 2B), the script would be:

A (find((abs(X) &lt; 0.5) &amp; (abs(Y) &lt; 0.5))) = 1; // values of x and y from -0.5 to 0.5

where abs() is a built-in function for taking absolute values.

Next up, would be to create a set of horizontal gratings, which can be created using loops:

for i=1:1:500
   for j=1:100:500       // 100 being the period for how the gratings repeat
      A(j:j+50, i) = 1;   // 50 being the width of every grating

This script, when displayed, results to a fairly striped image (Figure 3A).

Figure 3. A. horizontal gratings, B. 2D sinusoid

Diverting from binary matrices, a smooth 2D sinusoidal function is created by:

freqc = 5*%pi;      // frequency of the sinusoidal
A = sin(X*freqc);

Lastly, to produce a 2D Gaussian distribution (Figure 4), we write:

r = sqrt(X.^2 + Y.^2); // note element-per-element squaring of X and Y
A = exp(-4*r);         // 2D Gaussian

Figure 4. 2D Gaussian

Saving the image into a file takes the one-liner:

imwrite(A, 'gaussian.bmp'); // also works with png, jpg, tif and gif

That wraps up my initial set of familiarization on SciLab.  This just marks the beginning of an exciting bunch of image processing ahead.  One final note, I believe it is always best to develop good coding habits.  For SciLab coding standards, let me share the Code Conventions for the SciLab Programming Language.

For this section, I would rate myself 10 for being able to comprehend the important ideas and produce the desired outputs.


[1] Soriano, M. (2010). A2 – Scilab Basics. Applied Physics 186.