https://doi.org/10.5201/ipol.2011.blm-cdf
Revision 2ac5a1527b132f8930c5a8ec10cd641388a89e9e authored by Software Heritage on 01 January 2011, 00:00:00 UTC, committed by Software Heritage on 22 June 2011, 00:00:00 UTC
0 parent
Tip revision: 2ac5a1527b132f8930c5a8ec10cd641388a89e9e authored by Software Heritage on 01 January 2011, 00:00:00 UTC
ipol: Deposit 654 in collection ipol
ipol: Deposit 654 in collection ipol
Tip revision: 2ac5a15
rgbprocess_lib.cpp
/*
* Copyright (c) 2009-2010 Jose-Luis Lisani <joseluis.lisani@uib.es>
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file rgbprocess_lib.c
* @brief library for RGB cube processing
*
* @author Jose-Luis Lisani <joseluis.lisani@uib.es>
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* ensure consistency */
#include "rgbprocess_lib.h"
#include "cppcode/rgbcubeIPOL.h"
#include "cppcode/colorfilteringIPOL.h"
#include "cppcode/miscIPOL.h"
/**
* @file rgbprocess_lib.cpp
* @brief Operations on the RGB color cube (filtering, display density, ...)
*
*
*
* @author Jose-Luis Lisani <joseluis.lisani@uib.es>
*/
/**
* \brief Convert color data from 1 array with format
* RR...RRGG...GGBB...BB to 3 arrays with formats RRR..., GGG..., BBB...
*
*
* @param[in] input input array
* @param[out] RR, GG, BB output arrays
* @oaram[in] size number of colors
*
*/
void input2RGB(unsigned char *input,
unsigned char **RR, unsigned char **GG, unsigned char **BB,
int size)
{
unsigned char *R, *G, *B;
int n;
R=new unsigned char[size];
G=new unsigned char[size];
B=new unsigned char[size];
for (n=0; n < size; n++) {
R[n]=input[n];
G[n]=input[size+n];
B[n]=input[2*size+n];
}
*RR=R;
*GG=G;
*BB=B;
}
/**
* \brief Convert color data from 3 arrays with formats
* RRR..., GGG..., BBB... to 1 array with format RR...RRGG...GGBB...BB
*
*
* @param[in] R, G, B input arrays
* @param[out] output input array
* @oaram[in] size number of colors
*
*/
void RGB2output(unsigned char *R, unsigned char *G, unsigned char *B,
unsigned char *output, int size)
{
int n;
for (n=0; n < size; n++) {
output[n]=R[n];
output[size+n]=G[n];
output[2*size+n]=B[n];
}
}
/**
* @brief Main function: calls functions that perform different operations
* on the color cube
*
* @param[in] input1, input2, input3 input images
* @param[in] w, h dimensions of the input images
* @param[in] output1, output2, output3 output images
* @param[in] wOut, hOut dimensions of the output images
* @param[in] option processing option
*
* Processing options:
*
* filter: applies LLP2 algorithm to input1, saves result to output1
* (calls filtercolor function in rgbcubeIPOL.cpp)
*
* rmisolated: removes isolated color points from input1,
* saves result to output1
* (calls removeisolatedRGB function in colorfiltering.cpp)
*
* pcaviews: creates 3 images (output1, output2, output3) displaying
* the principal views of the RGB cube of image input1
* (calls function PCAviews in rgbcubeIPOL.cpp)
*
* pcaviewsB: creates 1 image (output1) displaying the 3 principal
* views of the RGB cube of image input1
* (calls function PCAviewsB in rgbcubeIPOL.cpp)
*
* densityviews: creates 1 image (output1) displaying the 3 principal
* views of the RGB cube of image input1,
* each color point is displayed with a grey level
* proportional to its density in the color cube
* (lighter for higher densities)
* (calls PCAviews_densityB in rgbcubeIPOL.cpp)
*
* densityImage: creates a gray-scale image (output1) with values
* proportional to the density of the colors of image input1
* (calls densityImage function in rgbcubeIPOL.cpp)
*
* mergeimages: creates one output image (output1) from two inputs
* (input1, input2) such that output1=input1 except at
* pixels with (0, 0, 0) RGB value, which are replaced by
* pixels of input2
*
* combineimages: creates one output image (output1) from three inputs
* (input1, input2, input3), arranged in horizontal direction
*
* combineimagesB: creates one output image (output1) from three inputs
* (input1, input2, input3), arranged in two rows: first row
* displays input1 and input2 and second row input3
* (centered)
*
*/
void rgbprocess(unsigned char *input1,
unsigned char *input2,
unsigned char *input3,
int w, int h,
unsigned char *output1,
unsigned char *output2,
unsigned char *output3,
int wOut, int hOut,
const char *option)
{
unsigned char *R1, *G1, *B1, *R2, *G2, *B2, *R3, *G3, *B3;
unsigned char *Rout1, *Gout1, *Bout1, *Rout2, *Gout2, *Bout2,
*Rout3, *Gout3, *Bout3;
R1=G1=B1=NULL;
R2=G2=B2=NULL;
R3=G3=B3=NULL;
Rout1=Gout1=Bout1=NULL;
Rout2=Gout2=Bout2=NULL;
Rout3=Gout3=Bout3=NULL;
if (!strcmp(option, "filter")) {
int type=2; //2D projection
int r=10; //radius of neirborhood
float eitmax=0.5f; //maximum mean error between corresponding points
//in consecutive iterations
int rsim=(r/2 > 0)?(r/2):(1); //acceleration parameter for PCA computation
printf("rsim=%i\n", rsim);
input2RGB(input1, &R1, &G1, &B1, w*h);
Rout1=new unsigned char[w*h];
Gout1=new unsigned char[w*h];
Bout1=new unsigned char[w*h];
filtercolor(R1, G1, B1, Rout1, Gout1, Bout1, w, h, type, eitmax, r, rsim);
RGB2output(Rout1, Gout1, Bout1, output1, w*h);
}
if (!strcmp(option, "rmisolated")) {
int r=5;
int nmin=10;
int nRGB, nisolatedRGB, nisolatedpixels;
input2RGB(input1, &R1, &G1, &B1, w*h);
Rout1=new unsigned char[w*h];
Gout1=new unsigned char[w*h];
Bout1=new unsigned char[w*h];
removeisolatedRGB(R1, G1, B1, Rout1, Gout1, Bout1, w, h, r, nmin, nRGB,
nisolatedRGB, nisolatedpixels);
RGB2output(Rout1, Gout1, Bout1, output1, w*h);
}
if (!strcmp(option, "pcaviews")) {
input2RGB(input1, &R1, &G1, &B1, w*h);
input2RGB(input2, &R2, &G2, &B2, w*h);
Rout1=new unsigned char[wOut*hOut];
Gout1=new unsigned char[wOut*hOut];
Bout1=new unsigned char[wOut*hOut];
Rout2=new unsigned char[wOut*hOut];
Gout2=new unsigned char[wOut*hOut];
Bout2=new unsigned char[wOut*hOut];
Rout3=new unsigned char[wOut*hOut];
Gout3=new unsigned char[wOut*hOut];
Bout3=new unsigned char[wOut*hOut];
PCAviews(R1, G1, B1, w, h, R2, G2, B2, w, h,
Rout1, Gout1, Bout1, Rout2, Gout2, Bout2,
Rout3, Gout3, Bout3, wOut, hOut);
RGB2output(Rout1, Gout1, Bout1, output1, wOut*hOut);
RGB2output(Rout2, Gout2, Bout2, output2, wOut*hOut);
RGB2output(Rout3, Gout3, Bout3, output3, wOut*hOut);
}
if (!strcmp(option, "pcaviewsB")) {
input2RGB(input1, &R1, &G1, &B1, w*h);
input2RGB(input2, &R2, &G2, &B2, w*h);
Rout1=new unsigned char[3*wOut*hOut];
Gout1=new unsigned char[3*wOut*hOut];
Bout1=new unsigned char[3*wOut*hOut];
PCAviewsB(R1, G1, B1, w, h, R2, G2, B2, w, h,
Rout1, Gout1, Bout1, wOut, hOut);
RGB2output(Rout1, Gout1, Bout1, output1, 3*wOut*hOut);
}
if (!strcmp(option, "densityImage")) {
int rdst=5;
unsigned char logscale=1;//use logarithmic scale
input2RGB(input1, &R1, &G1, &B1, w*h);
densityImage(R1, G1, B1, w, h, output1, rdst, logscale);
}
if (!strcmp(option, "densityviews")) {
int rdst=5;
unsigned char cumdsty=0;
input2RGB(input1, &R1, &G1, &B1, w*h);
input2RGB(input2, &R2, &G2, &B2, w*h);
unsigned char *Idsty=input3;
Rout1=new unsigned char[3*wOut*hOut];
Gout1=new unsigned char[3*wOut*hOut];
Bout1=new unsigned char[3*wOut*hOut];
PCAviews_densityB(R1, G1, B1, w, h, R2, G2, B2,
Rout1, Gout1, Bout1, wOut, hOut, rdst, cumdsty, Idsty);
RGB2output(Rout1, Gout1, Bout1, output1, 3*wOut*hOut);
}
if (!strcmp(option, "mergeimages")) {
input2RGB(input1, &R1, &G1, &B1, w*h);
input2RGB(input2, &R2, &G2, &B2, w*h);
Rout1=new unsigned char[w*h];
Gout1=new unsigned char[w*h];
Bout1=new unsigned char[w*h];
mergeimages(R1, G1, B1, R2, G2, B2, Rout1, Gout1, Bout1, w, h);
RGB2output(Rout1, Gout1, Bout1, output1, w*h);
}
if (!strcmp(option, "combineviews")) {
//view1 view2 view3
int wout=3*w;
int hout=h;
input2RGB(input1, &R1, &G1, &B1, w*h);
input2RGB(input2, &R2, &G2, &B2, w*h);
input2RGB(input3, &R3, &G3, &B3, w*h);
Rout1=new unsigned char[wout*hout];
Gout1=new unsigned char[wout*hout];
Bout1=new unsigned char[wout*hout];
for (int y=0; y < h; y++) {
memcpy(Rout1+y*wout, R1+y*w, w);
memcpy(Rout1+w+y*wout, R2+y*w, w);
memcpy(Rout1+2*w+y*wout, R3+y*w, w);
memcpy(Gout1+y*wout, G1+y*w, w);
memcpy(Gout1+w+y*wout, G2+y*w, w);
memcpy(Gout1+2*w+y*wout, G3+y*w, w);
memcpy(Bout1+y*wout, B1+y*w, w);
memcpy(Bout1+w+y*wout, B2+y*w, w);
memcpy(Bout1+2*w+y*wout, B3+y*w, w);
}
RGB2output(Rout1, Gout1, Bout1, output1, wout*hout);
}
if (!strcmp(option, "combineviewsB")) {
//view1 view2
// view3
int wout=2*w;
int hout=2*h;
input2RGB(input1, &R1, &G1, &B1, w*h);
input2RGB(input2, &R2, &G2, &B2, w*h);
input2RGB(input3, &R3, &G3, &B3, w*h);
Rout1=new unsigned char[wout*hout];
Gout1=new unsigned char[wout*hout];
Bout1=new unsigned char[wout*hout];
memset(Rout1, 255, wout*hout);
memset(Gout1, 255, wout*hout);
memset(Bout1, 255, wout*hout);
for (int y=0; y < h; y++) {
memcpy(Rout1+y*wout, R1+y*w, w);
memcpy(Gout1+y*wout, G1+y*w, w);
memcpy(Bout1+y*wout, B1+y*w, w);
memcpy(Rout1+w+y*wout, R2+y*w, w);
memcpy(Gout1+w+y*wout, G2+y*w, w);
memcpy(Bout1+w+y*wout, B2+y*w, w);
memcpy(Rout1+w/2+(h+y)*wout, R3+y*w, w);
memcpy(Gout1+w/2+(h+y)*wout, G3+y*w, w);
memcpy(Bout1+w/2+(h+y)*wout, B3+y*w, w);
}
RGB2output(Rout1, Gout1, Bout1, output1, wout*hout);
}
//clean up
if (R1) delete[] R1;
if (G1) delete[] G1;
if (B1) delete[] B1;
if (R2) delete[] R2;
if (G2) delete[] G2;
if (B2) delete[] B2;
if (R3) delete[] R3;
if (G3) delete[] G3;
if (B3) delete[] B3;
if (Rout1) delete[] Rout1;
if (Gout1) delete[] Gout1;
if (Bout1) delete[] Bout1;
if (Rout2) delete[] Rout2;
if (Gout2) delete[] Gout2;
if (Bout2) delete[] Bout2;
if (Rout3) delete[] Rout3;
if (Gout3) delete[] Gout3;
if (Bout3) delete[] Bout3;
return;
}
/**
* @brief Computes parameters (position and coordinates vectors)
* of a set of projection planes for displaying different views
* of the RGB color cube. Stores results in a text file
*
* @param[out] nameparams name of output file
*
* @see RGBviews_sequence_params
*
**/
void RGBviewsparams(const char *nameparams)
{
int nviews;
nviews=RGBviews_sequence_params(nameparams);
}
/**
* @brief Creates an image displaying the orthonormal projection of
* the RGB cube of a color image onto a plane defined by its position P
* in RGB space and by two coordinates vectors u, v
*
* @param[in] input input image
* @param[in] w, h input image dimensions
* @param[out] output output image
* @param[in] wview, hview output image dimensions
* @param[in] P position of projection plane in RGB space (center of the plane)
* @param[in] u, v vectors defining a coordinates system on the plane
*
* @see projectRGBcubeB
*
**/
void getRGBview(unsigned char *input,
int w, int h, unsigned char *I,
unsigned char *output,
int wview, int hview,
float P[3], float u[3], float v[3])
{
unsigned char *R, *G, *B, *Rout, *Gout, *Bout;
input2RGB(input, &R, &G, &B, w*h);
Rout=new unsigned char[wview*hview];
Gout=new unsigned char[wview*hview];
Bout=new unsigned char[wview*hview];
projectRGBcubeB(R, G, B, w*h, I, Rout, Gout, Bout, wview, hview, P, u, v);
RGB2output(Rout, Gout, Bout, output, wview*hview);
//clean up
if (R) delete[] R;
if (G) delete[] G;
if (B) delete[] B;
if (Rout) delete[] Rout;
if (Gout) delete[] Gout;
if (Bout) delete[] Bout;
}
/**
* @brief Compute Root Mean Squared Error (RMSE) and Average Distance (dmean)
* between two sets of colors in RGB space
*
* @param[in] input1, input2 input images whose colors are to be compared
* @param[in] w, h input image dimensions
* @param[out] dmean average distance between corresponding colors
*
* @return RMSE value
*
**/
float computeRMSE(unsigned char *input1, unsigned char *input2,
int w, int h, float &dmean)
{
float rmse;
unsigned char use_voxel;
unsigned char *R1, *G1, *B1, *R2, *G2, *B2;
input2RGB(input1, &R1, &G1, &B1, w*h);
input2RGB(input2, &R2, &G2, &B2, w*h);
use_voxel=1; //compute difference between color clouds
//(do not consider number of pixels associated to each color)
rmse=diffRMSE(R1, G1, B1, R2, G2, B2, w, h, 1, dmean);
//clean up
if (R1) delete[] R1;
if (G1) delete[] G1;
if (B1) delete[] B1;
if (R2) delete[] R2;
if (G2) delete[] G2;
if (B2) delete[] B2;
return rmse;
}
/**
* @brief Count the number of different colors in an image
*
* @param[in] input input image
* @param[in] w, h input image dimensions
*
* @return number of colors
*
**/
int countcolors(unsigned char *input, int w, int h)
{
int nRGB;
unsigned char *R, *G, *B;
input2RGB(input, &R, &G, &B, w*h);
nRGB=count_RGBcolors(R, G, B, w, h);
//clean up
if (R) delete[] R;
if (G) delete[] G;
if (B) delete[] B;
return nRGB;
}
/**
* @brief Creates a file in VRML 2.0 format containing the list of color points
* of an input image. Each point is either displayed with its original RGB color
* or with a gray level value proportional to the density of the color.
*
* @param[in] input input image
* @param[in] Idsty density image
* @param[out] nameout output file name
*
* @return number of colors
*
**/
void RGB2VRML2(unsigned char *input, int w, int h, unsigned char *Idsty,
const char *nameout)
{
unsigned char *R, *G, *B;
input2RGB(input, &R, &G, &B, w*h);
RGBcube2VRML2(R, G, B, w*h, Idsty, nameout);
//clean up
if (R) delete[] R;
if (G) delete[] G;
if (B) delete[] B;
}

Computing file changes ...