Initial import
git-svn-id: http://moon:8086/svn/software/trunk/libsrc/_to_be_added@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -0,0 +1,418 @@
|
||||
// ------------------------------------------------------------
|
||||
// clob.c
|
||||
//
|
||||
// A color quantizer using binary-split technique
|
||||
// From:
|
||||
// "Color Quantization of Images", Orchard, Bouman
|
||||
// IEEE Trans. on Sig. Proc., vol. 39, no. 12, pp. 2677-2690, Dec. 1991.
|
||||
//
|
||||
// 10.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include "bintree.h"
|
||||
#include "mutil.h"
|
||||
#include "lapack_cwrap.h"
|
||||
#include "clob.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void CodebookAlloc(codebook_t *pObj, int N_max, int M_max)
|
||||
{
|
||||
int i;
|
||||
|
||||
pObj->pColor = (color_vector_t*)malloc(M_max*sizeof(color_vector_t));
|
||||
pObj->size_C = (int*)malloc(M_max*sizeof(int));
|
||||
memset(pObj->size_C, 0, M_max*sizeof(int));
|
||||
pObj->pC = (int*)malloc(N_max*sizeof(int));
|
||||
pObj->ppC = (int**)malloc(M_max*sizeof(int*));
|
||||
|
||||
pObj->ppC[0] = pObj->pC;;
|
||||
for (i=1; i < M_max; i++)
|
||||
pObj->ppC[i] = NULL;
|
||||
|
||||
pObj->max_colors = M_max;
|
||||
pObj->max_samples = N_max;
|
||||
pObj->num_colors = 0;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void CodebookFree(codebook_t *pObj)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!pObj)
|
||||
return;
|
||||
|
||||
free(pObj->pC);
|
||||
free(pObj->ppC);
|
||||
free(pObj->pColor);
|
||||
free(pObj->size_C);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ColorQuant_Init(colorquant_t *pCQ, int N_max, int M_max)
|
||||
{
|
||||
M_max++;
|
||||
pCQ->N_max = N_max;
|
||||
pCQ->M_max = M_max;
|
||||
|
||||
pCQ->pRootData = (node_data_t*)malloc(sizeof(node_data_t));
|
||||
memset(pCQ->pRootData, 0, sizeof(node_data_t));
|
||||
|
||||
pCQ->pData = (node_data_t*)malloc(2*M_max*sizeof(node_data_t));
|
||||
memset(pCQ->pData, 0, 2*M_max*sizeof(node_data_t));
|
||||
|
||||
pCQ->pTemp = (double*)malloc(N_max*sizeof(double));
|
||||
pCQ->pXs = (color_vector_t*)malloc(N_max*sizeof(color_vector_t));
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ColorQuant_Free(colorquant_t *pCQ)
|
||||
{
|
||||
int m;
|
||||
|
||||
FreeNodeData(pCQ->pRootData);
|
||||
for (m=0; m < 2*pCQ->M_max; m++)
|
||||
{
|
||||
FreeNodeData(&pCQ->pData[m]);
|
||||
}
|
||||
free(pCQ->pRootData);
|
||||
pCQ->pRootData = NULL;
|
||||
free(pCQ->pData);
|
||||
pCQ->pData = NULL;
|
||||
free(pCQ->pXs);
|
||||
free(pCQ->pTemp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void FreeNodeData(node_data_t *pObj)
|
||||
{
|
||||
if(pObj)
|
||||
{
|
||||
if(pObj->pC)
|
||||
{
|
||||
free(pObj->pC);
|
||||
pObj->pC = NULL;
|
||||
}
|
||||
if(pObj->pExpr_left)
|
||||
{
|
||||
free(pObj->pExpr_left);
|
||||
pObj->pExpr_left = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ColorNodeStat(colorquant_t *pCQ, node_data_t *pObj, color_vector_t *pXs)
|
||||
{
|
||||
int i, j, s, info;
|
||||
|
||||
if (pObj->N == 0)
|
||||
{
|
||||
fprintf(stderr, "ColorNodeStat(): N is zero!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calc node statistics
|
||||
// R = sum_s(xs_s*xs_s') ; mit s = Element aus Menge C
|
||||
memset(pObj->R, 0, ROW_DIM*ROW_DIM*sizeof(double));
|
||||
dsyrk('U', 'N', ROW_DIM, pObj->N, 1.0, (double*)pXs, ROW_DIM, 1.0, (double*)pObj->R, ROW_DIM);
|
||||
// PrintMatrix("R=",(double*)pObj->R, ROW_DIM, ROW_DIM);
|
||||
|
||||
// m = sum_s(xs_s)
|
||||
memset(pObj->m, 0, ROW_DIM*sizeof(double));
|
||||
for(i=0; i < pObj->N; i++)
|
||||
{
|
||||
pObj->m[0] += pXs[i][0];
|
||||
pObj->m[1] += pXs[i][1];
|
||||
pObj->m[2] += pXs[i][2];
|
||||
|
||||
}
|
||||
// PrintMatrix("m=",(double*)pObj->m, ROW_DIM, 1);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
double ColorLambda(colorquant_t *pCQ, node_data_t *pObj, color_vector_t *pXs)
|
||||
{
|
||||
|
||||
int i, s, info, lwork;
|
||||
color_vector_t d = {0};
|
||||
double *pWork;
|
||||
double *pDiff, Ls;
|
||||
|
||||
if (pObj->N == 0)
|
||||
{
|
||||
fprintf(stderr, "ColorLambda(): N is zero!\n");
|
||||
pObj->lambda = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pObj->pExpr_left = (double*)malloc(pObj->N*sizeof(double));
|
||||
|
||||
// q = m/N;
|
||||
memcpy(pObj->q, pObj->m, sizeof(color_vector_t));
|
||||
dscal (ROW_DIM, 1.0/pObj->N, pObj->q, 1);
|
||||
// PrintMatrix("q=",(double*)pObj->q, ROW_DIM, 1);
|
||||
|
||||
// cov = R - 1/N*m*m'
|
||||
memcpy(pObj->cov, pObj->R, ROW_DIM*sizeof(color_vector_t));
|
||||
dsyr('U', ROW_DIM, -1.0/pObj->N, pObj->m, 1, (double*)pObj->cov, ROW_DIM);
|
||||
// PrintMatrix("Cov=",(double*)pObj->cov, ROW_DIM, ROW_DIM);
|
||||
|
||||
// Query dsyev() for optimal work buffer size
|
||||
pWork = pCQ->pTemp;
|
||||
pWork[0] = 0;
|
||||
info = dsyev('V', 'U', ROW_DIM, (double*)NULL, ROW_DIM, NULL, pWork, -1);
|
||||
lwork = (int)pWork[0];
|
||||
|
||||
// d = eig(cov)
|
||||
info = dsyev('V', 'U', ROW_DIM, (double*)pObj->cov, ROW_DIM, d, pWork, lwork);
|
||||
if (info != 0)
|
||||
{
|
||||
fprintf (stderr, "Eigenvalue solver failure with error %d\n", info);
|
||||
printf("N=%d\n", pObj->N);
|
||||
PrintMatrix("Cov=",(double*)pObj->cov, ROW_DIM, ROW_DIM);
|
||||
}
|
||||
|
||||
// PrintMatrix("d=",(double*)d, ROW_DIM, 1);
|
||||
// PrintMatrix("V=",(double*)pObj->cov, ROW_DIM, ROW_DIM);
|
||||
|
||||
// Form unit-vector e in direction of max. element in d
|
||||
dcopy (ROW_DIM, d, 1, pObj->e, 1);
|
||||
GetPrincipleEigenVector((double*)pObj->cov, (double*)pObj->e, ROW_DIM);
|
||||
// PrintMatrix("e=",(double*)pObj->e, ROW_DIM, 1);
|
||||
|
||||
// -------------------------
|
||||
// Compute Lambda
|
||||
|
||||
// Expr. left: dot(xs,e) = e'*xs_s = xs_s'*e
|
||||
// Also used later in ColorSplit()
|
||||
dgemv('T', ROW_DIM, pObj->N, 1.0, (double*)pXs, ROW_DIM, pObj->e, 1, 0.0, pObj->pExpr_left, 1);
|
||||
|
||||
// Expr. right: dot(q,e) = e'*q = q'*e
|
||||
// Also used later in ColorSplit()
|
||||
pObj->expr_right = ddot(ROW_DIM, pObj->q, 1, pObj->e, 1);
|
||||
|
||||
// lambda = sum_s((xs_s - q)'*e).^2);
|
||||
pObj->lambda = 0;
|
||||
for (i=0; i < pObj->N; i++)
|
||||
{
|
||||
// xs_s'*e - q'*e
|
||||
Ls = pObj->pExpr_left[i] - pObj->expr_right;
|
||||
pObj->lambda += Ls*Ls;
|
||||
}
|
||||
return pObj->lambda;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ColorNodeSplit(colorquant_t *pCQ, node_data_t *pObj, node_data_t *pData2n, node_data_t *pData2n1)
|
||||
{
|
||||
int N2n, N2n1, s, i;
|
||||
|
||||
memset(pData2n, 0, sizeof(node_data_t));
|
||||
memset(pData2n1, 0, sizeof(node_data_t));
|
||||
|
||||
pData2n->pC = (int*)malloc(pObj->N*sizeof(int));
|
||||
if(!pData2n->pC)
|
||||
{
|
||||
fprintf(stderr, "pData2n->pC = NULL for N=%d\n", pObj->N);
|
||||
}
|
||||
|
||||
pData2n1->pC = (int*)malloc(pObj->N*sizeof(int));
|
||||
if(!pData2n1->pC)
|
||||
{
|
||||
fprintf(stderr, "pData2n1->pC = NULL for N=%d\n", pObj->N);
|
||||
}
|
||||
|
||||
// Split into two new sets
|
||||
N2n = 0;
|
||||
N2n1 = 0;
|
||||
for (i=0; i < pObj->N; i++)
|
||||
{
|
||||
s = pObj->pC[i];
|
||||
|
||||
if(pObj->pExpr_left[i] > pObj->expr_right)
|
||||
{
|
||||
pData2n1->pC[N2n1] = s;
|
||||
N2n1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
pData2n->pC[N2n] = s;
|
||||
N2n++;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute statistics of two new nodes
|
||||
// Node(2n)
|
||||
pData2n->N = N2n;
|
||||
for (i=0; i < N2n; i++)
|
||||
{
|
||||
s = pData2n->pC[i];
|
||||
pCQ->pXs[i][0] = pCQ->pX[s][0];
|
||||
pCQ->pXs[i][1] = pCQ->pX[s][1];
|
||||
pCQ->pXs[i][2] = pCQ->pX[s][2];
|
||||
}
|
||||
|
||||
ColorNodeStat(pCQ, pData2n, pCQ->pXs);
|
||||
ColorLambda(pCQ, pData2n, pCQ->pXs);
|
||||
|
||||
// Node(2n+1)
|
||||
pData2n1->N = N2n1;
|
||||
for(i=0; i < ROW_DIM; i++)
|
||||
{
|
||||
pData2n1->R[i][0] = pObj->R[i][0] - pData2n->R[i][0];
|
||||
pData2n1->R[i][1] = pObj->R[i][1] - pData2n->R[i][1];
|
||||
pData2n1->R[i][2] = pObj->R[i][2] - pData2n->R[i][2];
|
||||
}
|
||||
|
||||
for(i=0; i < ROW_DIM; i++)
|
||||
pData2n1->m[i] = pObj->m[i] - pData2n->m[i];
|
||||
|
||||
for (i=0; i < N2n1; i++)
|
||||
{
|
||||
s = pData2n1->pC[i];
|
||||
pCQ->pXs[i][0] = pCQ->pX[s][0];
|
||||
pCQ->pXs[i][1] = pCQ->pX[s][1];
|
||||
pCQ->pXs[i][2] = pCQ->pX[s][2];
|
||||
}
|
||||
ColorLambda(pCQ, pData2n1, pCQ->pXs);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int ColorQuant(colorquant_t *pCQ, codebook_t *pCB, color_vector_t *pX, int K, int N, int M, double lambda_min)
|
||||
{
|
||||
int i, m, *pC, bst_state, s, sum_pixel, codebook_size, size, *ptr, *ptr_next;
|
||||
node_data_t *pData, *pData2n, *pData2n1;
|
||||
node_t *node_max, *node_temp;
|
||||
bintree_t bst;
|
||||
|
||||
if (N == 0)
|
||||
{
|
||||
fprintf(stderr, "ColorQuant(): N is zero!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCQ->nRow = K;
|
||||
pCQ->nCol = N;
|
||||
|
||||
pCQ->pRootData->N = N;
|
||||
pCQ->pX = (color_vector_t*)pX;
|
||||
|
||||
pCQ->pRootData->pC = (int*)malloc(N*sizeof(int));
|
||||
|
||||
// Create root data set
|
||||
for(i=0; i < N; i++)
|
||||
{
|
||||
pCQ->pRootData->pC[i] = i; // store indices of vector boundaries
|
||||
}
|
||||
|
||||
ColorNodeStat(pCQ, pCQ->pRootData, pCQ->pX);
|
||||
ColorLambda(pCQ, pCQ->pRootData, pCQ->pX);
|
||||
|
||||
// Create root-node
|
||||
bintree_init(&bst, 2*N);
|
||||
|
||||
bintree_insert(&bst, pCQ->pRootData->lambda, pCQ->pRootData);
|
||||
|
||||
for (m=0; m < M-1; m++)
|
||||
{
|
||||
node_max = bintree_GetNodeMax(&bst);
|
||||
if (!node_max)
|
||||
{
|
||||
fprintf(stderr,"node_max = NULL!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (node_max->value < lambda_min)
|
||||
break;
|
||||
|
||||
pData2n = &pCQ->pData[2*m];
|
||||
pData2n1 = &pCQ->pData[2*m+1];
|
||||
ColorNodeSplit(pCQ, (node_data_t*)node_max->pData, pData2n, pData2n1);
|
||||
if (pData2n->N > 0)
|
||||
{
|
||||
bintree_insert(&bst, pData2n->lambda, pData2n);
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeNodeData(pData2n);
|
||||
}
|
||||
|
||||
if (pData2n1->lambda > 0)
|
||||
{
|
||||
bintree_insert(&bst, pData2n1->lambda, pData2n1);
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeNodeData(pData2n1);
|
||||
}
|
||||
|
||||
// if ((pData2n->lambda == 0) || (pData2n1->lambda == 0))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
node_temp = bintree_node_remove(&bst, node_max);
|
||||
if (node_temp == bst.pRoot)
|
||||
{
|
||||
break;
|
||||
}
|
||||
FreeNodeData((node_data_t*)node_max->pData);
|
||||
|
||||
if (!bst.pRoot)
|
||||
break;
|
||||
|
||||
bst_state = bintree_isBST(bst.pRoot);
|
||||
if (!bst_state)
|
||||
{
|
||||
fprintf(stderr,"Binary Tree is not BST!\n");
|
||||
}
|
||||
}
|
||||
|
||||
// bintree_print(pCQ->root);
|
||||
// printf("\n");
|
||||
sum_pixel = 0;
|
||||
codebook_size = 0;
|
||||
pCB->ppC[0] = pCB->pC;
|
||||
do
|
||||
{
|
||||
node_max = bintree_GetNodeMax(&bst);
|
||||
if (!node_max)
|
||||
{
|
||||
fprintf(stderr,"node_max = NULL!\n");
|
||||
}
|
||||
// printf("Lambda=%5.5g\n",node_max->value);
|
||||
|
||||
size = ((node_data_t*)node_max->pData)->N;
|
||||
pCB->size_C[codebook_size] = size;
|
||||
ptr = pCB->ppC[codebook_size];
|
||||
ptr_next = ptr + size;
|
||||
sum_pixel += size;
|
||||
memcpy(ptr,((node_data_t*)node_max->pData)->pC, size*sizeof(int));
|
||||
memcpy(pCB->pColor[codebook_size],((node_data_t*)(node_max->pData))->q, sizeof(color_vector_t));
|
||||
if ((codebook_size+1) < pCB->max_colors)
|
||||
pCB->ppC[codebook_size+1] = (int*)(ptr_next);
|
||||
|
||||
FreeNodeData((node_data_t*)(node_max->pData));
|
||||
node_temp = bintree_node_remove(&bst, node_max);
|
||||
codebook_size++;
|
||||
|
||||
} while(node_temp);
|
||||
pCB->num_colors = codebook_size;
|
||||
|
||||
// printf("Num. pixels = %d\n",sum_pixel);
|
||||
// printf("Codebook size = %d\n",codebook_size);
|
||||
// PrintMatrix("Codebook=",(double*)pCB->pColor, ROW_DIM, codebook_size);
|
||||
|
||||
FreeNodeData(pCQ->pRootData);
|
||||
bintree_free(&bst);
|
||||
return codebook_size;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// ------------------------------------------------------------
|
||||
// clob.h
|
||||
//
|
||||
// A color quantizer using binary-split technique
|
||||
// From:
|
||||
// "Color Quantization of Images", Orchard, Bouman
|
||||
// IEEE Trans. on Sig. Proc., vol. 39, no. 12, pp. 2677-2690, Dec. 1991.
|
||||
//
|
||||
// 10.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#ifndef CLOB_H
|
||||
#define CLOB_H
|
||||
|
||||
#include "bintree.h"
|
||||
#include "colortypes.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define ROW_DIM 3
|
||||
|
||||
// ------------------------------------------------------------
|
||||
typedef struct _node_data_t
|
||||
{
|
||||
int N, *pC, len_C;
|
||||
color_vector_t R[ROW_DIM];
|
||||
color_vector_t cov[ROW_DIM];
|
||||
color_vector_t m;
|
||||
color_vector_t q;
|
||||
color_vector_t e;
|
||||
double lambda;
|
||||
double *pExpr_left, expr_right;
|
||||
|
||||
} node_data_t;
|
||||
|
||||
typedef struct _colorquant_t
|
||||
{
|
||||
int nRow, nCol, N_max, M_max, nPixel;
|
||||
double *pTemp;
|
||||
color_vector_t *pX, *pXs;
|
||||
node_data_t *pRootData, *pData;
|
||||
|
||||
} colorquant_t;
|
||||
|
||||
typedef struct _codebook_t
|
||||
{
|
||||
int num_colors, max_colors, max_samples;
|
||||
|
||||
color_vector_t *pColor;
|
||||
int **ppC, *pC, *size_C;
|
||||
|
||||
} codebook_t;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ColorQuant_Init(colorquant_t *pCQ, int N_max, int M_max);
|
||||
void ColorQuant_Free(colorquant_t *pCQ);
|
||||
void FreeNodeData(node_data_t *pObj);
|
||||
void ColorNodeStat(colorquant_t *pCQ, node_data_t *pObj, color_vector_t *pXs);
|
||||
double ColorLambda(colorquant_t *pCQ, node_data_t *pObj, color_vector_t *pXs);
|
||||
void ColorNodeSplit(colorquant_t *pCQ, node_data_t *pObj, node_data_t *pData2n, node_data_t *pData2n1);
|
||||
int ColorQuant(colorquant_t *pCQ, codebook_t *pCB, color_vector_t *pX, int K, int N, int M, double lambda_min);
|
||||
void CodebookAlloc(codebook_t *pObj, int N_max, int M_max);
|
||||
void CodebookFree(codebook_t *pObj);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#endif // CLOB_H
|
||||
Executable
+575
@@ -0,0 +1,575 @@
|
||||
// ----------------------------------------------------------------------
|
||||
// color_conv.c
|
||||
// 21.02.2005, Jens Ahrensfeld
|
||||
// ----------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "color_conv.h"
|
||||
#include "colortypes.h"
|
||||
#include "mutil.h"
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void rgb2hsv(color_vector_t *pRGB, color_vector_t *pHSV, int len)
|
||||
{
|
||||
int i;
|
||||
double *rgb, *hsv, v_min, v_max, diff_max, diff_max_r, diff_r, diff_g, diff_b;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
rgb = (double*)&pRGB[i];
|
||||
hsv = (double*)&pHSV[i];
|
||||
|
||||
v_min = smin(rgb[0], rgb[1]);
|
||||
v_min = smin(v_min, rgb[2]);
|
||||
|
||||
v_max = smax(rgb[0], rgb[1]);
|
||||
v_max = smax(v_max, rgb[2]);
|
||||
|
||||
diff_max = v_max - v_min;
|
||||
|
||||
hsv[2] = v_max;
|
||||
|
||||
if (diff_max == 0)
|
||||
{
|
||||
hsv[0] = diff_max;
|
||||
hsv[1] = diff_max;
|
||||
}
|
||||
else
|
||||
{
|
||||
diff_max_r = 1.0/diff_max;
|
||||
hsv[1] = diff_max/v_max;
|
||||
|
||||
diff_r = (((v_max - rgb[0])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
||||
diff_g = (((v_max - rgb[1])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
||||
diff_b = (((v_max - rgb[2])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
||||
|
||||
if (rgb[0] == v_max)
|
||||
{
|
||||
hsv[0] = diff_b - diff_g;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rgb[1] == v_max)
|
||||
{
|
||||
hsv[0] = 1.0/3 + diff_r - diff_b;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rgb[2] == v_max)
|
||||
{
|
||||
hsv[0] = 2.0/3 + diff_g - diff_r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hsv[0] < 0)
|
||||
hsv[0] += 1;
|
||||
|
||||
if (hsv[0] > 1.0)
|
||||
hsv[0] -= 1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void hsv2rgb(color_vector_t *pHSV, color_vector_t *pRGB, int len)
|
||||
{
|
||||
int i, j;
|
||||
double h, t1, t2, t3, *rgb, *hsv;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
rgb = (double*)&pRGB[i];
|
||||
hsv = (double*)&pHSV[i];
|
||||
|
||||
if (hsv[1] == 0)
|
||||
{
|
||||
rgb[0] = hsv[2];
|
||||
rgb[1] = hsv[2];
|
||||
rgb[2] = hsv[2];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
h = hsv[0] * 6;
|
||||
j = (int)h;
|
||||
t1 = hsv[2]*(1 - hsv[1]);
|
||||
t2 = hsv[2]*(1 - hsv[1]*(h-(double)j));
|
||||
t3 = hsv[2]*(1 - hsv[1]*(1-(h-(double)j)));
|
||||
|
||||
switch(j)
|
||||
{
|
||||
case 0:
|
||||
rgb[0] = hsv[2];
|
||||
rgb[1] = t3;
|
||||
rgb[2] = t1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rgb[0] = t2;
|
||||
rgb[1] = hsv[2];
|
||||
rgb[2] = t1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
rgb[0] = t1;
|
||||
rgb[1] = hsv[2];
|
||||
rgb[2] = t3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
rgb[0] = t1;
|
||||
rgb[1] = t2;
|
||||
rgb[2] = hsv[2];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rgb[0] = t3;
|
||||
rgb[1] = t1;
|
||||
rgb[2] = hsv[2];
|
||||
break;
|
||||
|
||||
default:
|
||||
rgb[0] = hsv[2];
|
||||
rgb[1] = t1;
|
||||
rgb[2] = t2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void rgb2hsl(color_vector_t *pRGB, color_vector_t *pHSL, int len)
|
||||
{
|
||||
int i;
|
||||
double *rgb, *hsl, v_min, v_max, diff_max, diff_max_r, diff_r, diff_g, diff_b;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
rgb = (double*)&pRGB[i];
|
||||
hsl = (double*)&pHSL[i];
|
||||
|
||||
v_min = smin(rgb[0], rgb[1]);
|
||||
v_min = smin(v_min, rgb[2]);
|
||||
|
||||
v_max = smax(rgb[0], rgb[1]);
|
||||
v_max = smax(v_max, rgb[2]);
|
||||
|
||||
diff_max = v_max - v_min;
|
||||
|
||||
hsl[2] = (v_max + v_min)/2;
|
||||
|
||||
if (diff_max == 0)
|
||||
{
|
||||
hsl[0] = diff_max;
|
||||
hsl[1] = diff_max;
|
||||
}
|
||||
else
|
||||
{
|
||||
diff_max_r = 1.0/diff_max;
|
||||
|
||||
if(hsl[2] < 0.5)
|
||||
{
|
||||
hsl[1] = diff_max/(v_max + v_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsl[1] = diff_max/(2 - v_max - v_min);
|
||||
}
|
||||
|
||||
diff_r = (((v_max - rgb[0])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
||||
diff_g = (((v_max - rgb[1])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
||||
diff_b = (((v_max - rgb[2])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
||||
|
||||
if (rgb[0] == v_max)
|
||||
{
|
||||
hsl[0] = diff_b - diff_g;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rgb[1] == v_max)
|
||||
{
|
||||
hsl[0] = 1.0/3 + diff_r - diff_b;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rgb[2] == v_max)
|
||||
{
|
||||
hsl[0] = 2.0/3 + diff_g - diff_r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hsl[0] < 0)
|
||||
hsl[0] += 1;
|
||||
|
||||
if (hsl[0] > 1.0)
|
||||
hsl[0] -= 1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
inline double Hue_2_RGB(double v1, double v2, double vH) //Function Hue_2_RGB
|
||||
{
|
||||
if (vH < 0)
|
||||
vH += 1;
|
||||
if (vH > 1)
|
||||
vH -= 1;
|
||||
|
||||
if ((6*vH) < 1)
|
||||
return v1 + (v2 - v1)*6*vH;
|
||||
|
||||
if ((2*vH) < 1)
|
||||
return v2;
|
||||
|
||||
if ((3*vH) < 2)
|
||||
return v1 + (v2 - v1)*((2.0/3) - vH)*6;
|
||||
|
||||
return v1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void hsl2rgb(color_vector_t *pHSL, color_vector_t *pRGB, int len)
|
||||
{
|
||||
int i, j;
|
||||
double h, t1, t2, t3, *rgb, *hsl;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
rgb = (double*)&pRGB[i];
|
||||
hsl = (double*)&pHSL[i];
|
||||
|
||||
if (hsl[1] == 0)
|
||||
{
|
||||
rgb[0] = hsl[2];
|
||||
rgb[1] = hsl[2];
|
||||
rgb[2] = hsl[2];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(hsl[2] < 0.5)
|
||||
{
|
||||
t2 = hsl[2]*(1 + hsl[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
t2 = (hsl[2] + hsl[1]) - hsl[2]*hsl[1];
|
||||
}
|
||||
|
||||
t1 = 2*hsl[2] - t2;
|
||||
|
||||
rgb[0] = Hue_2_RGB(t1, t2, hsl[0] + 1.0/3);
|
||||
rgb[1] = Hue_2_RGB(t1, t2, hsl[0]);
|
||||
rgb[2] = Hue_2_RGB(t1, t2, hsl[0] - 1.0/3);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void rgb2xyz(double **ppRGB, double **ppXYZ, int len)
|
||||
{
|
||||
int i, j;
|
||||
double rgb[3];
|
||||
double *pRGB, *pXYZ;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
pRGB = ((double*)ppRGB[i]);
|
||||
pXYZ = ((double*)ppXYZ[i]);
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
if (pRGB[j] > 0.04045)
|
||||
{
|
||||
rgb[j] = pow((pRGB[j]+0.055)/1.055,2.4);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgb[j] = 1.0/12.92 * pRGB[j];
|
||||
}
|
||||
|
||||
rgb[j] *= K_XYZ;
|
||||
|
||||
}
|
||||
|
||||
// Observer = 2°, Illuminant = D65
|
||||
pXYZ[0] = 0.412453*rgb[0] + 0.357580*rgb[1] + 0.180423*rgb[2];
|
||||
pXYZ[1] = 0.212671*rgb[0] + 0.715160*rgb[1] + 0.072169*rgb[2];
|
||||
pXYZ[2] = 0.019334*rgb[0] + 0.119193*rgb[1] + 0.950227*rgb[2];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void xyz2rgb(double **ppXYZ, double **ppRGB, int len)
|
||||
{
|
||||
int i, j;
|
||||
double xyz[3];
|
||||
double *pRGB, *pXYZ;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
pRGB = ((double*)ppRGB[i]);
|
||||
pXYZ = ((double*)ppXYZ[i]);
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
xyz[j] = 1.0/K_XYZ * pXYZ[j];
|
||||
}
|
||||
|
||||
// Observer = 2°, Illuminant = D65
|
||||
pRGB[0] = 3.240479*xyz[0] - 1.537150*xyz[1] - 0.498535*xyz[2];
|
||||
pRGB[1] = -0.969256*xyz[0] + 1.875992*xyz[1] + 0.041556*xyz[2];
|
||||
pRGB[2] = 0.055648*xyz[0] - 0.204043*xyz[1] + 1.057311*xyz[2];
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
if (pRGB[j] > 0.0031308)
|
||||
{
|
||||
pRGB[j] = 1.055 * pow(pRGB[j],1.0/2.4) - 0.055;
|
||||
}
|
||||
else
|
||||
{
|
||||
pRGB[j] = 12.92 * pRGB[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void xyz2lab(double **ppXYZ, double **ppLAB, double *pRef, int len)
|
||||
{
|
||||
int i, j;
|
||||
double xyz[3] = {0};
|
||||
double *pLAB, *pXYZ;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
pXYZ = ((double*)ppXYZ[i]);
|
||||
pLAB = ((double*)ppLAB[i]);
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
xyz[j] = pXYZ[j] / pRef[j];
|
||||
}
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
if (xyz[j] > 0.008856)
|
||||
{
|
||||
xyz[j] = pow(xyz[j],1.0/3.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
xyz[j] = 7.787*xyz[j] + 16.0/116.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pLAB[0] = 116.0*xyz[1] - 16;
|
||||
pLAB[1] = 500.0*(xyz[0] - xyz[1]);
|
||||
pLAB[2] = 200.0*(xyz[1] - xyz[2]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void lab2xyz(double **ppLAB, double **ppXYZ, double *pRef, int len)
|
||||
{
|
||||
int i, j;
|
||||
double xyz[3], xyz3;
|
||||
double *pLAB, *pXYZ;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
pXYZ = ((double*)ppXYZ[i]);
|
||||
pLAB = ((double*)ppLAB[i]);
|
||||
|
||||
xyz[1] = 1.0/116.0*(pLAB[0] + 16);
|
||||
xyz[0] = 1.0/500.0*pLAB[1] + xyz[1];
|
||||
xyz[2] = xyz[1] - 1.0/200.0*pLAB[2];
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
xyz3 = pow(xyz[j],3.0);
|
||||
if (xyz3 > 0.008856)
|
||||
{
|
||||
xyz[j] = xyz3;
|
||||
}
|
||||
else
|
||||
{
|
||||
xyz[j] = 1.0/7.787*(xyz[j] - 16.0/116);
|
||||
}
|
||||
}
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
pXYZ[j] = xyz[j] *pRef[j];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void tristimulus(double *pRef, unsigned illuminant_type, unsigned observer_type)
|
||||
{
|
||||
double ref[3] = {K_XYZ*0.95047, K_XYZ*1.0, K_XYZ*1.08883};
|
||||
|
||||
if(observer_type == OBS_TYPE_2DEG)
|
||||
{
|
||||
|
||||
switch (illuminant_type)
|
||||
{
|
||||
case ILLU_TYPE_A:
|
||||
case ILLU_TYPE_INCANDESCENT:
|
||||
pRef[0] = K_XYZ*1.09850;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.35585;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_C:
|
||||
pRef[0] = K_XYZ*0.98074;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.18232;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D50:
|
||||
pRef[0] = K_XYZ*0.96422;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.82521;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D55:
|
||||
pRef[0] = K_XYZ*0.95682;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.92149;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D65:
|
||||
case ILLU_TYPE_DAYLIGHT:
|
||||
pRef[0] = K_XYZ*0.95047;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.08883;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D75:
|
||||
pRef[0] = K_XYZ*0.94972;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.22638;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_F2:
|
||||
case ILLU_TYPE_FLUORESCENT:
|
||||
pRef[0] = K_XYZ*0.99187;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.67395;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_F7:
|
||||
pRef[0] = K_XYZ*0.95044;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.08755;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_F11:
|
||||
pRef[0] = K_XYZ*1.00966;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.64370;
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy(pRef, ref, 3*sizeof(double));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(observer_type == OBS_TYPE_10DEG)
|
||||
{
|
||||
|
||||
switch (illuminant_type)
|
||||
{
|
||||
case ILLU_TYPE_A:
|
||||
case ILLU_TYPE_INCANDESCENT:
|
||||
pRef[0] = K_XYZ*1.11144;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.35200;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_C:
|
||||
pRef[0] = K_XYZ*0.97285;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.16145;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D50:
|
||||
pRef[0] = K_XYZ*0.96720;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.81427;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D55:
|
||||
pRef[0] = K_XYZ*0.95799;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.90926;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D65:
|
||||
case ILLU_TYPE_DAYLIGHT:
|
||||
pRef[0] = K_XYZ*0.94811;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.07304;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_D75:
|
||||
pRef[0] = K_XYZ*0.94416;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.20641;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_F2:
|
||||
case ILLU_TYPE_FLUORESCENT:
|
||||
pRef[0] = K_XYZ*1.03280;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.69026;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_F7:
|
||||
pRef[0] = K_XYZ*0.95792;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*1.07687;
|
||||
break;
|
||||
|
||||
case ILLU_TYPE_F11:
|
||||
pRef[0] = K_XYZ*1.03866;
|
||||
pRef[1] = K_XYZ*1.0;
|
||||
pRef[2] = K_XYZ*0.65627;
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy(pRef, ref, 3*sizeof(double));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rgb2rgb(double **ppSrc, double **ppDst, int len)
|
||||
{
|
||||
int i, j;
|
||||
double *pSrc, *pDst;
|
||||
|
||||
for (i=0; i < len; i++)
|
||||
{
|
||||
pSrc = ((double*)ppSrc[i]);
|
||||
pDst = ((double*)ppDst[i]);
|
||||
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
pDst[j] = pSrc[j];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
// ----------------------------------------------------------------------
|
||||
// color_conv.h
|
||||
// 21.02.2005, Jens Ahrensfeld
|
||||
// ----------------------------------------------------------------------
|
||||
#ifndef COLOR_CONV_H
|
||||
#define COLOR_CONV_H
|
||||
|
||||
#include "colortypes.h"
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
#define K_XYZ 1.0
|
||||
|
||||
#define OBS_TYPE_2DEG 2
|
||||
#define OBS_TYPE_10DEG 10
|
||||
#define ILLU_TYPE_A 1
|
||||
#define ILLU_TYPE_C 2
|
||||
#define ILLU_TYPE_D50 3
|
||||
#define ILLU_TYPE_D55 4
|
||||
#define ILLU_TYPE_D65 5
|
||||
#define ILLU_TYPE_D75 6
|
||||
#define ILLU_TYPE_F2 7
|
||||
#define ILLU_TYPE_F7 8
|
||||
#define ILLU_TYPE_F11 9
|
||||
#define ILLU_TYPE_INCANDESCENT 10
|
||||
#define ILLU_TYPE_DAYLIGHT 11
|
||||
#define ILLU_TYPE_FLUORESCENT 12
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void rgb2hsv(color_vector_t *pRGB, color_vector_t *pHSV, int len);
|
||||
void hsv2rgb(color_vector_t *pHSV, color_vector_t *pRGB, int len);
|
||||
void rgb2hsl(color_vector_t *pRGB, color_vector_t *pHSL, int len);
|
||||
void hsl2rgb(color_vector_t *pHSL, color_vector_t *pRGB, int len);
|
||||
void rgb2xyz(double **ppRGB, double **ppXYZ, int len);
|
||||
void xyz2rgb(double **ppXYZ, double **ppRGB, int len);
|
||||
void xyz2lab(double **ppXYZ, double **ppLAB, double *pRef, int len);
|
||||
void lab2xyz(double **ppLAB, double **ppXYZ, double *pRef, int len);
|
||||
void rgb2rgb(double **ppSrc, double **ppDst, int len);
|
||||
void tristimulus(double *pRef, unsigned illuminant_type, unsigned observer_type);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
#endif // COLOR_CONV_H
|
||||
@@ -0,0 +1,225 @@
|
||||
// ------------------------------------------------------------
|
||||
// imageio.c
|
||||
//
|
||||
// Reading writing tiff images
|
||||
//
|
||||
// 12.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include <tiffio.h>
|
||||
#include "mtypes.h"
|
||||
#include "imageio.h"
|
||||
#include "mutil.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ImageInit(image_t *pObj, int num_row, int num_col, int num_ch)
|
||||
{
|
||||
pObj->num_row = num_row;
|
||||
pObj->num_col = num_col;
|
||||
pObj->num_ch = num_ch;
|
||||
pObj->num_pixel = num_row*num_col;
|
||||
|
||||
pObj->pColor_data = (double*)malloc(pObj->num_pixel*num_ch*sizeof(double));
|
||||
memset(pObj->pColor_data, 0, pObj->num_pixel*num_ch*sizeof(double));
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ImageFree(image_t *pObj)
|
||||
{
|
||||
pObj->num_row = 0;
|
||||
pObj->num_col = 0;
|
||||
pObj->num_pixel = 0;
|
||||
pObj->num_ch = 0;
|
||||
|
||||
if (pObj->pColor_data)
|
||||
|
||||
free(pObj->pColor_data);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ImageCopy(image_t *pSrc, image_t *pDst)
|
||||
{
|
||||
pDst->num_row = pSrc->num_row;
|
||||
pDst->num_col = pSrc->num_col;
|
||||
pDst->num_pixel = pSrc->num_pixel;
|
||||
pDst->num_ch = pSrc->num_ch;
|
||||
|
||||
if (!pDst->pColor_data)
|
||||
pDst->pColor_data = (double*)malloc(pSrc->num_ch*pSrc->num_pixel*sizeof(double));
|
||||
|
||||
|
||||
memcpy(pDst->pColor_data, pSrc->pColor_data, pSrc->num_ch*pSrc->num_pixel*sizeof(double));
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int ImageLoadTiff(image_t *pObj, char *filename)
|
||||
{
|
||||
|
||||
TIFF *pTifComp;
|
||||
UINT16 config, nBits, nSamples, photometric;
|
||||
UINT32 i, num_col, num_row, scan_size, size, num_color_ch;
|
||||
double k_norm;
|
||||
double c;
|
||||
|
||||
UINT8 *pImage_comp8;
|
||||
int status;
|
||||
|
||||
pTifComp = TIFFOpen(filename,"r");
|
||||
|
||||
if (!pTifComp)
|
||||
{
|
||||
fprintf(stderr,"Unable to open input file %s\n",filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = TIFFGetField(pTifComp, TIFFTAG_IMAGEWIDTH, &num_col);
|
||||
status = TIFFGetField(pTifComp, TIFFTAG_IMAGELENGTH, &num_row);
|
||||
status = TIFFGetField(pTifComp, TIFFTAG_BITSPERSAMPLE, &nBits);
|
||||
status = TIFFGetField(pTifComp, TIFFTAG_PLANARCONFIG, &config);
|
||||
status = TIFFGetField(pTifComp, TIFFTAG_PHOTOMETRIC, &photometric);
|
||||
status = TIFFGetField(pTifComp, TIFFTAG_SAMPLESPERPIXEL, &nSamples);
|
||||
|
||||
num_color_ch = (UINT32)nSamples;
|
||||
pObj->num_row = num_row;
|
||||
pObj->num_col = num_col;
|
||||
pObj->num_pixel = num_row*num_col;
|
||||
pObj->num_ch = num_color_ch;
|
||||
|
||||
pObj->pColor_data = (double*)malloc(num_color_ch*pObj->num_pixel*sizeof(double));
|
||||
|
||||
scan_size = TIFFScanlineSize(pTifComp);
|
||||
|
||||
pImage_comp8 = (UINT8*)_TIFFmalloc(scan_size*num_row*sizeof(UINT8));
|
||||
|
||||
for (i=0; i < num_row; i++)
|
||||
status = TIFFReadScanline(pTifComp, &pImage_comp8[i*scan_size], i, 0);
|
||||
|
||||
TIFFClose(pTifComp);
|
||||
|
||||
k_norm = 1.0/(pow(2.0,nBits)-1);
|
||||
|
||||
for (i=0; i < num_color_ch*num_col*num_row; i++)
|
||||
{
|
||||
c = k_norm*(double)pImage_comp8[i];
|
||||
pObj->pColor_data[i] = c;
|
||||
}
|
||||
|
||||
free(pImage_comp8);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int ImageSaveTiff(image_t *pObj, double *pAlpha, char *filename)
|
||||
{
|
||||
|
||||
TIFF *pTifComp;
|
||||
ttag_t config, nBits, nSamples, photometric, extra_sample_info;
|
||||
UINT32 i, num_col, num_row, scan_size, size;
|
||||
double k_norm;
|
||||
double c, a;
|
||||
|
||||
UINT8 *pImage_comp8;
|
||||
int status;
|
||||
|
||||
pTifComp = TIFFOpen(filename,"w");
|
||||
|
||||
if (!pTifComp)
|
||||
{
|
||||
fprintf(stderr,"Unable to open input file %s\n",filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nBits = 8;
|
||||
num_row = pObj->num_row;
|
||||
num_col = pObj->num_col;
|
||||
config = PLANARCONFIG_CONTIG;
|
||||
photometric = PHOTOMETRIC_RGB;
|
||||
|
||||
nSamples = (ttag_t)pObj->num_ch;
|
||||
|
||||
extra_sample_info = 0;
|
||||
if (pAlpha)
|
||||
{
|
||||
nSamples++;
|
||||
extra_sample_info = EXTRASAMPLE_ASSOCALPHA;
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_EXTRASAMPLES, 1, &extra_sample_info);
|
||||
|
||||
}
|
||||
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_IMAGEWIDTH, num_col);
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_IMAGELENGTH, num_row);
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_ROWSPERSTRIP, num_row);
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_BITSPERSAMPLE, nBits);
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_PLANARCONFIG, config);
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_SAMPLESPERPIXEL, nSamples);
|
||||
status = TIFFSetField(pTifComp, TIFFTAG_ARTIST, "JDI, J. Ahrensfeld");
|
||||
|
||||
//TIFFTAG_IMAGEDESCRIPTION
|
||||
//TIFFTAG_SOFTWARE 305 /* name & release */
|
||||
//TIFFTAG_DATETIME 306 /* creation date and time */
|
||||
|
||||
scan_size = nSamples*num_col;
|
||||
|
||||
pImage_comp8 = (UINT8*)_TIFFmalloc(scan_size*num_row*sizeof(UINT8));
|
||||
|
||||
k_norm = pow(2.0,nBits)-1;
|
||||
|
||||
if (pAlpha)
|
||||
{
|
||||
for (i=0; i < num_col*num_row; i++)
|
||||
{
|
||||
a = smin(smax(pAlpha[i],0),1);
|
||||
|
||||
c = pObj->pColor_data[(nSamples-1)*i+0];
|
||||
c = a*smin(smax(c,0),1);
|
||||
pImage_comp8[nSamples*i+0] = (UINT8)(k_norm*c);
|
||||
|
||||
c = pObj->pColor_data[(nSamples-1)*i+1];
|
||||
c = a*smin(smax(c,0),1);
|
||||
pImage_comp8[nSamples*i+1] = (UINT8)(k_norm*c);
|
||||
|
||||
c = pObj->pColor_data[(nSamples-1)*i+2];
|
||||
c = a*smin(smax(c,0),1);
|
||||
pImage_comp8[nSamples*i+2] = (UINT8)(k_norm*c);
|
||||
|
||||
pImage_comp8[nSamples*i+3] = (UINT8)(k_norm*a);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < nSamples*num_col*num_row; i++)
|
||||
{
|
||||
c = pObj->pColor_data[i];
|
||||
c = smin(smax(c,0),1);
|
||||
pImage_comp8[i] = (UINT8)(k_norm*c);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i < num_row; i++)
|
||||
{
|
||||
status = TIFFWriteScanline(pTifComp, &pImage_comp8[i*scan_size], i, 0);
|
||||
if (status < 0)
|
||||
TIFFError("ImageSaveTiff", "%s", "Hallo") ;
|
||||
}
|
||||
|
||||
TIFFClose(pTifComp);
|
||||
free(pImage_comp8);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// ------------------------------------------------------------
|
||||
// imageio.h
|
||||
//
|
||||
// Reading writing tiff images
|
||||
//
|
||||
// 12.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#ifndef IMAGEIO_H
|
||||
#define IMAGEIO_H
|
||||
|
||||
#include "mtypes.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
typedef struct _image_t
|
||||
{
|
||||
UINT32 num_row, num_col, num_pixel, num_ch;
|
||||
double *pColor_data;
|
||||
|
||||
} image_t;
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ImageInit(image_t *pObj, int num_row, int num_col, int num_ch);
|
||||
void ImageFree(image_t *pObj);
|
||||
void ImageCopy(image_t *pSrc, image_t *pDst);
|
||||
int ImageLoadTiff(image_t *pObj, char *filename);
|
||||
int ImageSaveTiff(image_t *pObj, double *pAlpha, char *filename);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#endif // IMAGEIO_H
|
||||
Executable
+350
@@ -0,0 +1,350 @@
|
||||
// ------------------------------------------------------------
|
||||
// lapack_cwrap.c
|
||||
// Wrapping LAPACK FORTRAN-function to C-Functions
|
||||
// Libraries needed:
|
||||
// lapack.a blas.a and libg2c.a (if available)
|
||||
//
|
||||
// 26.02.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// LAPACK functions
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
|
||||
extern
|
||||
void dgesv_(int *N, int *NHRS, double *A, int *LDA,
|
||||
int *IPIV, double *B, int *LDB, int *INFO);
|
||||
|
||||
int dgesv(int N, int NHRS, double *A, int LDA, int *IPIV,
|
||||
double *B, int LDB)
|
||||
{
|
||||
int info;
|
||||
|
||||
dgesv_(&N, &NHRS, A, &LDA, IPIV, B, &LDB, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )
|
||||
extern
|
||||
void dsyev_(char *JOBZ, char *UPLO, int *N, double *A, int *LDA,
|
||||
double *W, double *WORK, int *LWORK, int *INFO);
|
||||
|
||||
int dsyev(char JOBZ, char UPLO, int N, double *A, int LDA,
|
||||
double *W, double *WORK, int LWORK)
|
||||
{
|
||||
int info;
|
||||
|
||||
dsyev_(&JOBZ, &UPLO, &N, A, &LDA, W, WORK, &LWORK, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Extern declaration of FORTRAN routine
|
||||
extern
|
||||
void dgtsv_(int *Np, int *NRHSp, double *DL, double *D, double *DU,
|
||||
double *B, int *LDBp, int *INFOp);
|
||||
|
||||
// C-Wrapper function
|
||||
int dgtsv(int N, int NRHS, double *DL, double *D, double *DU,
|
||||
double *B, int ldb)
|
||||
{
|
||||
int info;
|
||||
dgtsv_ (&N, &NRHS, DL, D, DU, B, &ldb, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO )
|
||||
extern
|
||||
void dgebrd_(int *M, int *N, double *A, int *LDA, double *D, double *E,
|
||||
double *TAUQ, double *TAUP, double *WORK, int *LWORK, int *INFO);
|
||||
|
||||
int dgebrd(int M, int N, double *A, int LDA, double *D, double *E,
|
||||
double *TAUQ, double *TAUP, double *WORK, int LWORK)
|
||||
|
||||
{
|
||||
int info;
|
||||
dgebrd_(&M, &N, A, &LDA, D, E, TAUQ, TAUP, WORK, &LWORK, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DBDSQR( UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U,
|
||||
// LDU, C, LDC, WORK, INFO )
|
||||
extern
|
||||
void dbdsqr_(char *UPLO, int *N, int *NCVT, int *NRU, int *NCC, double *D,
|
||||
double *E, double *VT, int *LDVT, double *U, int *LDU,
|
||||
double *C, int *LDC, double *WORK, int *INFO);
|
||||
|
||||
int dbdsqr(char UPLO, int N, int NCVT, int NRU, int NCC, double *D,
|
||||
double *E, double *VT, int LDVT, double *U, int LDU,
|
||||
double *C, int LDC, double *WORK)
|
||||
{
|
||||
int info;
|
||||
dbdsqr_(&UPLO, &N, &NCVT, &NRU, &NCC, D, E, VT, &LDVT, U, &LDU,
|
||||
C, &LDC, WORK, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
int dgesvd(char JOBU, char JOBVT, int M, int N, double *A, int LDA, double *S,
|
||||
double *U, int LDU, double *VT, int LDVT, double *WORK, int LWORK);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
|
||||
// WORK, LWORK, INFO )
|
||||
extern
|
||||
void dgesvd_(char *JOBU, char *JOBVT, int *M, int *N, double *A, int *LDA,
|
||||
double *S, double *U, int *LDU, double *VT, int *LDVT,
|
||||
double *WORK, int *LWORK, int *INFO);
|
||||
|
||||
int dgesvd(char JOBU, char JOBVT, int M, int N, double *A, int LDA, double *S,
|
||||
double *U, int LDU, double *VT, int LDVT, double *WORK, int LWORK)
|
||||
{
|
||||
int info;
|
||||
dgesvd_(&JOBU, &JOBVT, &M, &N, A, &LDA, S, U, &LDU, VT, &LDVT,
|
||||
WORK, &LWORK, &info);
|
||||
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO )
|
||||
extern
|
||||
void dgetri_(int *N, double *A, int *LDA, int *IPIV, double *WORK, int *LWORK, int *INFO);
|
||||
|
||||
int dgetri(int N, double *A, int LDA, int *IPIV, double *WORK, int LWORK)
|
||||
{
|
||||
|
||||
int info;
|
||||
dgetri_(&N, A, &LDA, IPIV, WORK, &LWORK, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DPOTRI( UPLO, N, A, LDA, INFO )
|
||||
extern
|
||||
void dpotri_(char *UPLO, int *N, double *A, int *LDA, int *INFO);
|
||||
|
||||
int dpotri(char UPLO, int N, double *A, int LDA)
|
||||
{
|
||||
|
||||
int info;
|
||||
dpotri_(&UPLO, &N, A, &LDA, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DGECON( NORM, N, A, LDA, ANORM, RCOND, WORK, IWORK, INFO )
|
||||
extern
|
||||
void dgecon_(char *NORM, int *N, double *A, int *LDA, double *ANORM, double *RCOND,
|
||||
double *DWORK, int *IWORK, int *INFO);
|
||||
|
||||
int dgecon(char NORM, int N, double *A, int LDA, double ANORM, double *RCOND,
|
||||
double *DWORK, int *IWORK)
|
||||
{
|
||||
int info;
|
||||
dgecon_(&NORM, &N, A, &LDA, &ANORM, RCOND, DWORK, IWORK, &info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// BLAS functions LEVEL 1
|
||||
// ------------------------------------------------------------
|
||||
// subroutine dswap(n,dx,incx,dy,incy)
|
||||
// interchanges two vectors.
|
||||
extern
|
||||
void dswap_ (int *n, double *dx, int *incx, double *dy, int *incy);
|
||||
|
||||
void dswap (int n, double *dx, int incx, double *dy, int incy)
|
||||
{
|
||||
dswap_ (&n, dx, &incx, dy, &incy);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// subroutine dcopy(n,dx,incx,dy,incy)
|
||||
// copies a vector, x, to a vector, y.
|
||||
extern
|
||||
void dcopy_ (int *n, double *dx, int *incx, double *dy, int *incy);
|
||||
|
||||
void dcopy (int n, double *dx, int incx, double *dy, int incy)
|
||||
{
|
||||
dcopy_ (&n, dx, &incx, dy, &incy);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// subroutine dscal(n,da,dx,incx)
|
||||
// scales a vector by a constant.
|
||||
extern
|
||||
void dscal_ (int *n, double *da, double *dx, int *incx);
|
||||
|
||||
void dscal (int n, double da, double *dx, int incx)
|
||||
{
|
||||
dscal_ (&n, &da, dx, &incx);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// subroutine daxpy(n,da,dx,incx,dy,incy)
|
||||
// constant times a vector plus a vector.
|
||||
extern
|
||||
void daxpy_ (int *n, double *da, double *dx, int *incx, double *dy, int *incy);
|
||||
|
||||
void daxpy (int n, double da, double *dx, int incx, double *dy, int incy)
|
||||
{
|
||||
daxpy_ (&n, &da, dx, &incx, dy, &incy);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// function ddot(n,dx,incx,dy,incy)
|
||||
// forms the dot product of two vectors.
|
||||
extern
|
||||
double ddot_ (int *n, double *dx, int *incx, double *dy, int *incy);
|
||||
|
||||
double ddot (int n, double *dx, int incx, double *dy, int incy)
|
||||
{
|
||||
return ddot_ (&n, dx, &incx, dy, &incy);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// function DNRM2 ( N, X, INCX )
|
||||
// DNRM2 returns the euclidean norm of a vector via the function
|
||||
// DNRM2 := sqrt( x'*x )
|
||||
extern
|
||||
double dnrm2_ (int *n, double *dx, int *incx);
|
||||
|
||||
double dnrm2 (int n, double *dx, int incx)
|
||||
{
|
||||
return dnrm2_ (&n, dx, &incx);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// function dasum(n,dx,incx)
|
||||
// takes the sum of the absolute values.
|
||||
extern
|
||||
double dasum_ (int *n, double *dx, int *incx);
|
||||
|
||||
double dasum (int n, double *dx, int incx)
|
||||
{
|
||||
return dasum_ (&n, dx, &incx);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// function idamax(n,dx,incx)
|
||||
// finds the index of element having max. absolute value.
|
||||
extern
|
||||
int idamax_ (int *n, double *dx, int *incx);
|
||||
|
||||
int idamax (int n, double *dx, int incx)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = idamax_ (&n, dx, &incx);
|
||||
|
||||
if (i > 0)
|
||||
return i - 1;
|
||||
else
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// BLAS functions LEVEL 2
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// SUBROUTINE DGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY )
|
||||
extern
|
||||
void dgemv_(char *TRANS, int *M, int *N, double *ALPHA, double *A, int *LDA,
|
||||
double *X, int *INCX, double *BETA, double *Y, int *INCY);
|
||||
|
||||
void dgemv(char TRANS, int M, int N, double ALPHA, double *A, int LDA,
|
||||
double *X, int INCX, double BETA, double *Y, int INCY)
|
||||
{
|
||||
|
||||
dgemv_(&TRANS, &M, &N, &ALPHA, A, &LDA, X, &INCX, &BETA, Y, &INCY);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DGER ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA )
|
||||
extern void dger_(int *m,int *n, double *alpha, double *x, int *incx,
|
||||
double *y, int *incy, double *A, int *lda);
|
||||
|
||||
void dger(int m,int n, double alpha, double *x, int incx,
|
||||
double *y, int incy, double *A, int lda)
|
||||
{
|
||||
dger_(&m, &n, &alpha, x, &incx, y, &incy, A, &lda);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SUBROUTINE DSYR ( UPLO, N, ALPHA, X, INCX, A, LDA )
|
||||
extern void dsyr_(char *UPLO, int *n, double *alpha, double *x, int *incx,
|
||||
double *A, int *lda);
|
||||
|
||||
void dsyr(char UPLO, int n, double alpha, double *x, int incx, double *A, int lda)
|
||||
{
|
||||
dsyr_(&UPLO, &n, &alpha, x, &incx, A, &lda);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// BLAS functions LEVEL 3
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// SUBROUTINE DSYRK ( UPLO, TRANS, N, K, ALPHA, A, LDA,
|
||||
extern
|
||||
void dsyrk_(char *UPLO, char *TRANS, int *N, int *K, double *ALPHA,
|
||||
double *A, int *LDA, double *BETA, double *C, int *LDC);
|
||||
|
||||
void dsyrk(char UPLO, char TRANS, int N, int K, double ALPHA,
|
||||
double *A, int LDA, double BETA, double *C, int LDC)
|
||||
{
|
||||
dsyrk_(&UPLO, &TRANS, &N, &K, &ALPHA, A, &LDA, &BETA, C, &LDC);
|
||||
}
|
||||
|
||||
// SUBROUTINE DGEMM ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB,
|
||||
extern
|
||||
void dgemm_(char *TRANSA, char *TRANSB, int *M, int *N, int *K, double *ALPHA,
|
||||
double *A, int *LDA, double *B, int *LDB, double *BETA, double *C, int *LDC);
|
||||
|
||||
void dgemm(char TRANSA, char TRANSB, int M, int N, int K, double ALPHA,
|
||||
double *A, int LDA, double *B, int LDB, double BETA, double *C, int LDC)
|
||||
{
|
||||
|
||||
dgemm_(&TRANSA, &TRANSB, &M, &N, &K, &ALPHA, A, &LDA, B, &LDB, &BETA, C, &LDC);
|
||||
|
||||
}
|
||||
|
||||
// SUBROUTINE DTRMM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA,
|
||||
extern
|
||||
void dtrmm_(char *SIDE, char *UPLO, char *TRANSA, char *DIAG, int *M, int *N,
|
||||
double *ALPHA, double *A, int *LDA, double *B, int *LDB);
|
||||
|
||||
void dtrmm(char SIDE, char UPLO, char TRANSA, char DIAG, int M, int N,
|
||||
double ALPHA, double *A, int LDA, double *B, int LDB)
|
||||
{
|
||||
|
||||
dtrmm_(&SIDE, &UPLO, &TRANSA, &DIAG, &M, &N, &ALPHA, A, &LDA, B, &LDB);
|
||||
|
||||
}
|
||||
|
||||
// SUBROUTINE DTRSM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA,
|
||||
extern
|
||||
void dtrsm_(char *SIDE, char *UPLO, char *TRANSA, char *DIAG, int *M, int *N,
|
||||
double *ALPHA, double *A, int *LDA, double *B, int *LDB);
|
||||
|
||||
void dtrsm(char SIDE, char UPLO, char TRANSA, char DIAG, int M, int N,
|
||||
double ALPHA, double *A, int LDA, double *B, int LDB)
|
||||
{
|
||||
|
||||
dtrsm_(&SIDE, &UPLO, &TRANSA, &DIAG, &M, &N, &ALPHA, A, &LDA, B, &LDB);
|
||||
|
||||
}
|
||||
|
||||
Executable
+1389
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,977 @@
|
||||
// ------------------------------------------------------------
|
||||
// matte.c
|
||||
//
|
||||
// Natural image matting using bayesian statistics
|
||||
// From:
|
||||
//
|
||||
//
|
||||
//
|
||||
// 19.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include "lapack_cwrap.h"
|
||||
#include "mlio.h"
|
||||
#include "mutil.h"
|
||||
#include "clob.h"
|
||||
#include "mtypes.h"
|
||||
#include "imageio.h"
|
||||
#include "pixel.h"
|
||||
#include "tictoc.h"
|
||||
#include "matte.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
//#define MATTE_DEBUG
|
||||
//#define WITH_COND_COMPUTING
|
||||
#define USE_SLIDING_WINDOW
|
||||
#define WITH_SETSIZE_BY_MAJOR
|
||||
//#define WITH_ANIMATION
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#ifdef USE_SLIDING_WINDOW
|
||||
#undef WITH_SETSIZE_BY_MAJOR
|
||||
#endif
|
||||
|
||||
#define SIGMA_C 0.3
|
||||
#define SIGMA_GF 8
|
||||
#define SQRT_2PI 2.506628274631000502415765284811
|
||||
#define LAMBDA_THRESH 0.6
|
||||
#define MAX_COLORS 16
|
||||
#define RADIUS_MIN 4.0
|
||||
#define RADIUS_MAX 50
|
||||
#define WEIGHTS_MIN 0.001
|
||||
#define ALPHA_CONV_THRESH 0.001
|
||||
#define ALPHA_TAU 0.33
|
||||
#define SOLVER_MAX_ITER 30
|
||||
#define SOLVER_EPS_COND 1E-12
|
||||
#define REPORT_INTERVAL 1
|
||||
// ------------------------------------------------------------
|
||||
void AlphaInit(set_data_t *pObj, double *pAlpha, UINT32 type)
|
||||
{
|
||||
int i;
|
||||
pixel_t *pPixel = pObj->pPixel;
|
||||
|
||||
if (type == pixel_state_foreground)
|
||||
{
|
||||
for (i=0; i < pObj->num_pixel; i++)
|
||||
{
|
||||
switch(pPixel[i].state)
|
||||
{
|
||||
case pixel_state_background:
|
||||
pAlpha[i] = 0.0;
|
||||
break;
|
||||
|
||||
case pixel_state_foreground:
|
||||
pAlpha[i] = 1.0;
|
||||
break;
|
||||
|
||||
case pixel_state_unknown:
|
||||
pAlpha[i] = 0.5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (i=0; i < pObj->num_pixel; i++)
|
||||
{
|
||||
switch(pPixel[i].state)
|
||||
{
|
||||
case pixel_state_background:
|
||||
pAlpha[i] = 1.0;
|
||||
break;
|
||||
|
||||
case pixel_state_foreground:
|
||||
pAlpha[i] = 0.0;
|
||||
break;
|
||||
|
||||
case pixel_state_unknown:
|
||||
pAlpha[i] = 0.5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void MatteInit(matte_t *pObj, image_t *pComposite, image_t *pTrimap, char *name, matte_settings_t *pSettings)
|
||||
{
|
||||
double k_norm[2];
|
||||
|
||||
int result, i, s;
|
||||
tictoc_t tictoc;
|
||||
char filename[1024];
|
||||
image_t im_dist_f, im_dist_b;
|
||||
int num_row, num_col, num_unknown;
|
||||
pxl_id_t t_f, t_b;
|
||||
pixel_t *pPixel;
|
||||
|
||||
color_vector_t *pColor_dist_f, *pColor_dist_b;
|
||||
|
||||
num_row = pComposite->num_row;
|
||||
num_col = pComposite->num_col;
|
||||
|
||||
pObj->pWork = (double*)malloc(num_row*num_col*sizeof(double));
|
||||
|
||||
// Copy settings
|
||||
memcpy(&pObj->settings, pSettings, sizeof(matte_settings_t));
|
||||
strcpy(pObj->name, name);
|
||||
|
||||
SetInit(&pObj->comp_set, num_row, num_col);
|
||||
|
||||
printf("Evaluating Trimap data...");
|
||||
Tic(&tictoc);
|
||||
PixelStateInit(&pObj->comp_set, pTrimap);
|
||||
ImageFree(pTrimap);
|
||||
|
||||
// Init Alpha map
|
||||
ImageInit(&pObj->im_alpha_f, num_row, num_col, 1);
|
||||
AlphaInit(&pObj->comp_set, pObj->im_alpha_f.pColor_data, pixel_state_foreground);
|
||||
|
||||
// Init 1-Alpha map
|
||||
ImageInit(&pObj->im_alpha_b, num_row, num_col, 1);
|
||||
AlphaInit(&pObj->comp_set, pObj->im_alpha_b.pColor_data, pixel_state_background);
|
||||
|
||||
// Init probability map
|
||||
ImageInit(&pObj->im_P, num_row, num_col, 1);
|
||||
|
||||
// Get number of unknown pixels
|
||||
num_unknown = GetSetByState(&pObj->comp_set, NULL, pixel_state_unknown);
|
||||
pObj->pCalcSet = (pxl_id_t*)malloc(num_unknown*sizeof(pxl_id_t));
|
||||
|
||||
printf("done\n");
|
||||
Toc(&tictoc);
|
||||
|
||||
// Create fore- and background images
|
||||
ImageInit(&pObj->im_f, num_row, num_col, 3);
|
||||
ImageInit(&pObj->im_b, num_row, num_col, 3);
|
||||
ImageCopy(pComposite, &pObj->im_f);
|
||||
ImageCopy(pComposite, &pObj->im_b);
|
||||
|
||||
sprintf(filename, "%s_calcset.dat",name);
|
||||
result = LoadCalcSet(filename, &pObj->comp_set, pObj->pCalcSet, num_unknown);
|
||||
|
||||
// If loading of calcset fails - compute a new one
|
||||
if (result < 0)
|
||||
{
|
||||
printf("Computing distance map...");
|
||||
Tic(&tictoc);
|
||||
|
||||
// Get unknown pixels
|
||||
num_unknown = GetSetByState(&pObj->comp_set, pObj->pCalcSet, pixel_state_unknown);
|
||||
|
||||
// Compute distance map for unknown pixel
|
||||
ComputeDistanceMap(&pObj->comp_set, pObj->pCalcSet, num_unknown);
|
||||
|
||||
printf("done\n");
|
||||
Toc(&tictoc);
|
||||
|
||||
printf("Computing calc set...");
|
||||
Tic(&tictoc);
|
||||
|
||||
// Compute calcset base on distance map for unknown pixel
|
||||
ComputeCalcSet(&pObj->comp_set, pObj->pCalcSet, num_unknown);
|
||||
SaveCalcSet(filename, &pObj->comp_set, pObj->pCalcSet, num_unknown);
|
||||
|
||||
printf("done\n");
|
||||
Toc(&tictoc);
|
||||
|
||||
}
|
||||
|
||||
ImageInit(&im_dist_f, num_row, num_col, 3);
|
||||
ImageInit(&im_dist_b, num_row, num_col, 3);
|
||||
|
||||
printf("Computing images from distance maps for %d unknown pixels...",num_unknown);
|
||||
Tic(&tictoc);
|
||||
|
||||
k_norm[0] = 1.0/num_col;
|
||||
k_norm[1] = 1.0/num_row;
|
||||
|
||||
pPixel = pObj->comp_set.pPixel;
|
||||
pColor_dist_f = (color_vector_t*)im_dist_f.pColor_data;
|
||||
pColor_dist_b = (color_vector_t*)im_dist_b.pColor_data;
|
||||
|
||||
for (i=0; i < num_unknown; i++)
|
||||
{
|
||||
s = pObj->pCalcSet[i];
|
||||
t_f = pPixel[s].id_closest_f;
|
||||
t_b = pPixel[s].id_closest_b;
|
||||
|
||||
pColor_dist_f[s][0] = k_norm[0]*(double)pPixel[t_f].raster_coord[0];
|
||||
pColor_dist_f[s][2] = k_norm[1]*(double)pPixel[t_f].raster_coord[1];
|
||||
|
||||
pColor_dist_b[s][0] = k_norm[0]*(double)pPixel[t_b].raster_coord[0];
|
||||
pColor_dist_b[s][2] = k_norm[1]*(double)pPixel[t_b].raster_coord[1];
|
||||
}
|
||||
|
||||
printf("done\n");
|
||||
Toc(&tictoc);
|
||||
|
||||
sprintf(filename, "%s_dist_f.tif",name);
|
||||
result = ImageSaveTiff(&im_dist_f, NULL, filename);
|
||||
sprintf(filename, "%s_dist_b.tif",name);
|
||||
result = ImageSaveTiff(&im_dist_b, NULL, filename);
|
||||
|
||||
ImageFree(&im_dist_f);
|
||||
ImageFree(&im_dist_b);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void MatteFree(matte_t *pObj)
|
||||
{
|
||||
if (!pObj)
|
||||
return;
|
||||
|
||||
if (pObj->pWork)
|
||||
free(pObj->pWork);
|
||||
|
||||
if (pObj->pCalcSet)
|
||||
free(pObj->pCalcSet);
|
||||
|
||||
SetFree(&pObj->comp_set);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int MatteGetSet(set_data_t *pObj, pxl_id_t *pPid, pxl_id_t pid, double *pAlpha, double *radius, UINT32 types)
|
||||
{
|
||||
|
||||
int i, s, num_found;
|
||||
pos_t center;
|
||||
pixel_t *pPixel = pObj->pPixel;
|
||||
double err, errlast, errslope, mean_weight;
|
||||
double diff[2], a, d, s2_i, d_offset, sum_weight, w;
|
||||
|
||||
s2_i = 1.0/(SIGMA_GF*SIGMA_GF);
|
||||
|
||||
memcpy(center, pPixel[pid].raster_coord, sizeof(pos_t));
|
||||
|
||||
err = 0;
|
||||
errlast = 0;
|
||||
errslope = 1;
|
||||
num_found = 0;
|
||||
// A = r^2*pi
|
||||
// r = sqrt(A/pi)
|
||||
|
||||
do
|
||||
{
|
||||
err = 1 - num_found;
|
||||
|
||||
if (err < 0)
|
||||
*radius -= sqrt(-err/M_PI);
|
||||
else
|
||||
*radius += sqrt(err/M_PI);
|
||||
|
||||
num_found = GetCircleSet(pObj, pPid, center, *radius, types);
|
||||
|
||||
errslope = err - errlast;
|
||||
errlast = err;
|
||||
|
||||
} while (num_found == 0);
|
||||
|
||||
sum_weight = 0;
|
||||
do
|
||||
{
|
||||
|
||||
sum_weight = 0;
|
||||
for (i=0; i < num_found; i++)
|
||||
{
|
||||
s = pPid[i];
|
||||
diff[0] = (double)(center[0] - pPixel[s].raster_coord[0]);
|
||||
diff[1] = (double)(center[1] - pPixel[s].raster_coord[1]);
|
||||
d = dnrm2(2, diff, 1);
|
||||
a = pAlpha[s];
|
||||
// w = a*a/(d*d);
|
||||
w = a*a*exp(-s2_i*d*d)*(1.0/SQRT_2PI);
|
||||
sum_weight += w;
|
||||
}
|
||||
mean_weight = sum_weight/num_found;
|
||||
|
||||
if (sum_weight < WEIGHTS_MIN)
|
||||
{
|
||||
*radius += 1;
|
||||
num_found = GetCircleSet(pObj, pPid, center, *radius, types);
|
||||
}
|
||||
|
||||
} while ((sum_weight < WEIGHTS_MIN) && (*radius < RADIUS_MAX));
|
||||
|
||||
// printf("numfound = %d\n",num_found);
|
||||
return num_found;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int MatteGetColor(pxl_id_t *pPid, color_vector_t *pSrc, color_vector_t *pDst, int num_pixel)
|
||||
{
|
||||
int i, s;
|
||||
|
||||
for(i=0; i < num_pixel; i++)
|
||||
{
|
||||
s = pPid[i];
|
||||
pDst[i][0] = pSrc[s][0];
|
||||
pDst[i][1] = pSrc[s][1];
|
||||
pDst[i][2] = pSrc[s][2];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int MatteGetData(pxl_id_t *pPid, double *pSrc, double *pDst, int num_pixel)
|
||||
{
|
||||
int i, s;
|
||||
|
||||
for(i=0; i < num_pixel; i++)
|
||||
{
|
||||
s = pPid[i];
|
||||
pDst[i] = pSrc[s];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int MatteComputeWeights(set_data_t *pObj, pxl_id_t pid_u, pxl_id_t *pPid, double *pAlpha, double *pWeight, int num_pixel, double radius, UINT32 type)
|
||||
{
|
||||
int i, s;
|
||||
pos_t center;
|
||||
double diff[2], a, d, s2_i, d_offset, sum_weight, alpha_mean;
|
||||
|
||||
pixel_t *pPixel = pObj->pPixel;
|
||||
|
||||
memcpy(center, pPixel[pid_u].raster_coord, sizeof(pos_t));
|
||||
|
||||
#ifndef USE_SLIDING_WINDOW
|
||||
if (type == pixel_state_foreground)
|
||||
{
|
||||
d_offset = pPixel[pid_u].dist_closest_f;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_offset = pPixel[pid_u].dist_closest_b;
|
||||
}
|
||||
|
||||
d_offset = smax(d_offset-radius, 0);
|
||||
#else
|
||||
d_offset = 0;
|
||||
#endif
|
||||
|
||||
s2_i = 1.0/(SIGMA_GF*SIGMA_GF);
|
||||
|
||||
// d = exp(-s2_i*radius*radius)*(1.0/SQRT_2PI);
|
||||
// printf("r=%f, min(d)=%f\n",radius,d);
|
||||
|
||||
sum_weight = 0;
|
||||
alpha_mean = 0;
|
||||
for (i=0; i < num_pixel; i++)
|
||||
{
|
||||
s = pPid[i];
|
||||
diff[0] = (double)(center[0] - pPixel[s].raster_coord[0]);
|
||||
diff[1] = (double)(center[1] - pPixel[s].raster_coord[1]);
|
||||
d = dnrm2(2, diff, 1);
|
||||
d = smax(d - d_offset, 0);
|
||||
a = pAlpha[s];
|
||||
pWeight[i] = a*a*exp(-s2_i*d*d)*(1.0/SQRT_2PI);
|
||||
// pWeight[i] = 1.0;
|
||||
sum_weight += pWeight[i];
|
||||
alpha_mean += a;
|
||||
}
|
||||
|
||||
alpha_mean /= num_pixel;
|
||||
if (alpha_mean < SOLVER_EPS_COND)
|
||||
fprintf(stderr, "ComputeWeights(): alpha_mean = %f\n", alpha_mean);
|
||||
|
||||
if (sum_weight < SOLVER_EPS_COND)
|
||||
fprintf(stderr, "ComputeWeights(): Sum_i(w_i) = %f\n", sum_weight);
|
||||
|
||||
return num_pixel;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ColorStatInit(color_stat_t *pObj, int max_pixel, int max_colors, UINT32 type)
|
||||
{
|
||||
int info;
|
||||
double lwork_svd, lwork_inv;
|
||||
|
||||
pObj->type = type;
|
||||
// Init SVD
|
||||
// Query work size
|
||||
info = dgesvd(/*JOBU*/'A', /*JOBVT*/'A', /*M*/3, /*N*/3, /*A*/NULL, /*LDA*/3, /*S*/NULL,
|
||||
/*U*/NULL, /*LDU*/3, /*VT*/NULL, /*LDVT*/3, /*WORK*/&lwork_svd, /*LWORK*/-1);
|
||||
|
||||
if (info != 0) fprintf (stderr, "Init SVD failure with error %d\n", info);
|
||||
|
||||
// Matrix inversion
|
||||
// Query work size
|
||||
info = dgetri(3, NULL, 3, NULL, &lwork_inv, -1);
|
||||
if (info != 0) fprintf (stderr, "Init dgetri failure with error %d\n", info);
|
||||
|
||||
pObj->work_size = (int)smax(lwork_svd, lwork_inv);
|
||||
pObj->work_size_svd = (int)lwork_svd;
|
||||
pObj->work_size_inv = (int)lwork_inv;
|
||||
pObj->pWork = (double*)malloc(pObj->work_size*sizeof(double));
|
||||
pObj->pColor_mean = (color_vector_t*)malloc(max_colors*sizeof(color_vector_t));
|
||||
pObj->pCov_inv = (color_matrix_t*)malloc(max_colors*sizeof(color_matrix_t));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void ColorStatFree(color_stat_t *pObj)
|
||||
{
|
||||
|
||||
if (!pObj)
|
||||
return;
|
||||
|
||||
if (pObj->pWork)
|
||||
free(pObj->pWork);
|
||||
|
||||
if (pObj->pColor_mean)
|
||||
free(pObj->pColor_mean);
|
||||
|
||||
if (pObj->pCov_inv)
|
||||
free(pObj->pCov_inv);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int ColorStatProcess(matte_t *pObj, color_stat_t *pStat, codebook_t *pCB, color_vector_t *pColor_set, int set_len, double *pWeight, double sigma_c)
|
||||
{
|
||||
int i, j, num_colors, info, ipiv[3]={0};
|
||||
color_vector_t *pColor_data, *pColor_data_w, sv={0};
|
||||
color_vector_t color_mean={0};
|
||||
color_matrix_t cov={0}, cov1={0}, cov2={0}, cov_i={0}, U={0}, S={0}, VT={0}, T={0};
|
||||
double *pW, k_weight, sum_weight, s2, norm_cov, norm_cov_i, cond_cov;
|
||||
|
||||
pW = (double*)malloc(set_len*sizeof(double));
|
||||
pColor_data = (color_vector_t*)malloc(set_len*sizeof(color_vector_t));
|
||||
|
||||
s2 = sigma_c*sigma_c;
|
||||
|
||||
// Loop over number of colors found
|
||||
pStat->num_colors = 0;
|
||||
for (i=0; i < pCB->num_colors; i++)
|
||||
{
|
||||
num_colors = pCB->size_C[i];
|
||||
|
||||
// Get color values from Cluster i
|
||||
MatteGetColor((pxl_id_t*)pCB->ppC[i], pColor_set, pColor_data, num_colors);
|
||||
|
||||
// Get corresponding weights of pixels from Cluster i
|
||||
MatteGetData((pxl_id_t*)pCB->ppC[i], pWeight, pW, num_colors);
|
||||
|
||||
// k_weight = 1.0/sum_i(pW[i])
|
||||
sum_weight = dasum(num_colors, pW, 1);
|
||||
if (sum_weight == 0)
|
||||
{
|
||||
// for(j=0; j < num_colors; j++)
|
||||
// pW[j] = 1.0;
|
||||
|
||||
// sum_weight = num_colors;
|
||||
continue;
|
||||
}
|
||||
|
||||
k_weight = 1.0/sum_weight;
|
||||
if (isinf(k_weight))
|
||||
continue;
|
||||
|
||||
// color_mean := k_weight*[sum_i(pW[i]*pColorData[i])]
|
||||
memset(color_mean, 0, sizeof(color_vector_t));
|
||||
dgemv('N', 3, num_colors, k_weight, (double*)pColor_data, 3, (double*)pW, 1, 0.0, (double*)color_mean, 1);
|
||||
|
||||
// Remove mean from color data
|
||||
for (j=0; j < num_colors; j++)
|
||||
{
|
||||
pColor_data[j][0] -= color_mean[0];
|
||||
pColor_data[j][1] -= color_mean[1];
|
||||
pColor_data[j][2] -= color_mean[2];
|
||||
}
|
||||
|
||||
// cov = k_weight*pColor_data*pColor_data'
|
||||
memset(cov, 0, sizeof(color_matrix_t));
|
||||
for (j=0; j < num_colors; j++)
|
||||
{
|
||||
dsyr('U', 3, pW[j], (double*)pColor_data[j], 1, (double*)cov, 3);
|
||||
}
|
||||
|
||||
cov[0][1] = cov[1][0];
|
||||
cov[0][2] = cov[2][0];
|
||||
cov[1][2] = cov[2][1];
|
||||
|
||||
// Scaling of cov
|
||||
for (j=0; j < 3; j++)
|
||||
{
|
||||
cov[j][0] *= k_weight;
|
||||
cov[j][1] *= k_weight;
|
||||
cov[j][2] *= k_weight;
|
||||
}
|
||||
|
||||
// Do the Singular Value Decomposition
|
||||
memcpy(cov1, cov, sizeof(color_matrix_t));
|
||||
info = dgesvd(/*JOBU*/'A', /*JOBVT*/'A', /*M*/3, /*N*/3, /*A*/(double*)cov1, /*LDA*/3,
|
||||
/*S*/(double*)sv, /*U*/(double*)U, /*LDU*/3,
|
||||
/*VT*/(double*)VT, /*LDVT*/3,
|
||||
/*WORK*/(double*)pStat->pWork, /*LWORK*/pStat->work_size_svd);
|
||||
|
||||
if (info != 0) fprintf (stderr, "SVD failure with error %d\n", info);
|
||||
|
||||
// Add camera variance to singular value
|
||||
sv[0] += s2;
|
||||
sv[1] += s2;
|
||||
sv[2] += s2;
|
||||
|
||||
// Compose new covariance matrix
|
||||
MakeDiag((double*)S, sv, 3);
|
||||
memset(T, 0, 3*sizeof(color_vector_t));
|
||||
memset(cov2, 0, 3*sizeof(color_vector_t));
|
||||
|
||||
dgemm('N', 'N', 3, 3, 3, 1.0, (double*)U, 3, (double*)S, 3, 0.0, (double*)T, 3);
|
||||
dgemm('N', 'N', 3, 3, 3, 1.0, (double*)T, 3, (double*)VT, 3, 0.0, (double*)cov2, 3);
|
||||
|
||||
//#ifdef WITH_COND_COMPUTING
|
||||
norm_cov = dnrm(3, 3, (double*)cov2, '1'); // 1-norm
|
||||
//#endif
|
||||
// Cov_inf = cov^-1;
|
||||
Eye((double*)cov_i, 1.0, 3);
|
||||
info = dgesv(3, 3, (double*)*cov2, 3, ipiv, (double*)cov_i, 3);
|
||||
if (info != 0)
|
||||
{
|
||||
fprintf (stderr, "Matrix inversion failure with error %d\n", info);
|
||||
}
|
||||
|
||||
//#ifdef WITH_COND_COMPUTING
|
||||
norm_cov_i = dnrm(3, 3, (double*)cov_i, '1'); // 1-norm
|
||||
cond_cov = 1.0/(norm_cov*norm_cov_i);
|
||||
|
||||
if (cond_cov < SOLVER_EPS_COND)
|
||||
fprintf(stderr, "Condition(cov) = %f\n", cond_cov);
|
||||
//#endif
|
||||
|
||||
memcpy(pStat->pColor_mean[pStat->num_colors], color_mean, sizeof(color_vector_t));
|
||||
memcpy(pStat->pCov_inv[pStat->num_colors], cov_i, sizeof(color_matrix_t));
|
||||
pStat->num_colors++;
|
||||
}
|
||||
|
||||
free(pColor_data);
|
||||
free(pW);
|
||||
|
||||
return pStat->num_colors;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void InsertMatrix(double *A, int lda, double *B, int ldb, int subid)
|
||||
{
|
||||
int i, j, k, m;
|
||||
|
||||
m = lda/ldb;
|
||||
|
||||
k = ldb*(subid%m);
|
||||
if (ldb*subid >= lda)
|
||||
k += lda*ldb;
|
||||
|
||||
for (i=0; i < ldb; i++)
|
||||
for (j=0; j < ldb; j++)
|
||||
A[j+i*lda+k] = B[i*ldb+j];
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int MatteEstimate(matte_sol_t *pObj, color_vector_t colorComp, color_stat_t *pStat_f, color_stat_t *pStat_b, double sigma_c)
|
||||
{
|
||||
int i, j, k, iteration, info, ipiv[6], is_valid;
|
||||
double *pW_f, *pW_b, alpha, b0, a0;
|
||||
double a_s2, b_s2, ab_s2, s2_i, c[6], c_orig[6], c_last[6], x[6];
|
||||
color_matrix_t A[4] = {0}, A_orig[4], I, T, cov_f, cov_b;
|
||||
color_vector_t colorMean_f, colorMean_b, t, c1, c2;
|
||||
double a1, a2, delta_alpha, alpha_lt, L_f, L_b, L_sol;
|
||||
double norm_A, rcond_A, dwork[24];
|
||||
int iwork[6];
|
||||
|
||||
// Find solution loop
|
||||
s2_i = 1.0/(sigma_c*sigma_c);
|
||||
|
||||
// ----------------------------
|
||||
// Loop begin
|
||||
memset(pObj, 0, sizeof(matte_sol_t));
|
||||
pObj->L = -1.0/SOLVER_EPS_COND;
|
||||
|
||||
if ((pStat_f->num_colors * pStat_b->num_colors) == 0)
|
||||
fprintf(stderr, "MatteEstimate(): No solution possible!\n");
|
||||
|
||||
for (i=0; i < pStat_f->num_colors; i++)
|
||||
{
|
||||
memcpy(cov_f, pStat_f->pCov_inv[i], sizeof(color_matrix_t));
|
||||
memcpy(colorMean_f, pStat_f->pColor_mean[i], sizeof(color_vector_t));
|
||||
|
||||
for (j=0; j < pStat_b->num_colors; j++)
|
||||
{
|
||||
|
||||
memcpy(cov_b, pStat_b->pCov_inv[j], sizeof(color_matrix_t));
|
||||
memcpy(colorMean_b, pStat_b->pColor_mean[j], sizeof(color_vector_t));
|
||||
|
||||
delta_alpha = 1;
|
||||
iteration = 0;
|
||||
alpha = 0.5;
|
||||
alpha_lt = 1.0;
|
||||
while((delta_alpha > ALPHA_CONV_THRESH) && (iteration < SOLVER_MAX_ITER))
|
||||
{
|
||||
memcpy(c_last, c, 6*sizeof(double));
|
||||
|
||||
is_valid = 0;
|
||||
a0 = smin(smax(alpha,0),1);
|
||||
b0 = 1.0-a0;
|
||||
|
||||
// alpha/sigma_c^2
|
||||
a_s2 = a0*s2_i;
|
||||
|
||||
// (1-alpha)/sigma_c^2
|
||||
b_s2 = b0*s2_i;
|
||||
|
||||
// A = [[inv_C_F+(I*a0^2)/sigma_c^2 (I*a0*(1-a0))/sigma_c^2]
|
||||
// ; [(I*a0*(1-a0))/sigma_c^2 inv_C_B+(I*(1-a0)^2)/sigma_c^2]];
|
||||
|
||||
memcpy(T, cov_f, sizeof(color_matrix_t));
|
||||
for (k=0; k < 3; k++)
|
||||
{
|
||||
T[k][k] += (a0*a_s2);
|
||||
}
|
||||
InsertMatrix((double*)A, 6, (double*)T, 3, 0);
|
||||
|
||||
Eye((double*)T, a0*b_s2, 3);
|
||||
InsertMatrix((double*)A, 6, (double*)T, 3, 1);
|
||||
InsertMatrix((double*)A, 6, (double*)T, 3, 2);
|
||||
|
||||
memcpy(T, cov_b, sizeof(color_matrix_t));
|
||||
for (k=0; k < 3; k++)
|
||||
{
|
||||
T[k][k] += (b0*b_s2);
|
||||
}
|
||||
InsertMatrix((double*)A, 6, (double*)T, 3, 3);
|
||||
|
||||
#ifdef WITH_COND_COMPUTING
|
||||
// Checking condition of A
|
||||
norm_A = dnrm(6, 6, (double*)A, '1'); // 1-norm
|
||||
info = dgecon('1', 6, (double*)A, 6, norm_A, &rcond_A, dwork, iwork);
|
||||
if (info != 0)
|
||||
{
|
||||
fprintf (stderr, "Condition estimator failure with error %d\n", info);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rcond_A < SOLVER_EPS_COND)
|
||||
{
|
||||
fprintf(stderr, "Cond(A) = %g\n", rcond_A);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
// c = [[inv_C_F*color_mean_F+(color_C*a0)/sigma_c^2]
|
||||
// ; [inv_C_B*color_mean_B+(color_C*(1-a0))/sigma_c^2]];
|
||||
memcpy(t, colorComp, sizeof(color_vector_t));
|
||||
dgemv('N', 3, 3, 1.0, (double*)cov_f, 3, (double*)colorMean_f, 1, a_s2, t, 1);
|
||||
memcpy(&c[0], t, sizeof(color_vector_t));
|
||||
|
||||
memcpy(t, colorComp, sizeof(color_vector_t));
|
||||
dgemv('N', 3, 3, 1.0, (double*)cov_b, 3, (double*)colorMean_b, 1, b_s2, t, 1);
|
||||
memcpy(&c[3], t, sizeof(color_vector_t));
|
||||
|
||||
// Solve
|
||||
// x = A/c
|
||||
memcpy(A_orig, A, 4*sizeof(color_matrix_t));
|
||||
memcpy(c_orig, c, 6*sizeof(double));
|
||||
info = dgesv(6, 1, (double*)A, 6, ipiv, (double*)c, 6);
|
||||
if (info != 0)
|
||||
{
|
||||
fprintf (stderr, "Solver failure with error %d\n", info);
|
||||
#ifdef MATTE_DEBUG
|
||||
PrintMatrix("A=", (double*)A_orig, 6, 6);
|
||||
PrintMatrix("c=", (double*)c_orig, 1, 6);
|
||||
PrintMatrix("Cov_f=", (double*)cov_f, 3, 3);
|
||||
PrintMatrix("Cov_b=", (double*)cov_b, 3, 3);
|
||||
fprintf(stderr, "a0 = %f\n", a0);
|
||||
#endif
|
||||
// If solver fails just copy meanF into F and meanB into B
|
||||
memcpy(&c[0], colorMean_f, sizeof(color_vector_t));
|
||||
memcpy(&c[3], colorMean_b, sizeof(color_vector_t));
|
||||
}
|
||||
|
||||
// C - B
|
||||
c1[0] = colorComp[0] - c[3];
|
||||
c1[1] = colorComp[1] - c[4];
|
||||
c1[2] = colorComp[2] - c[5];
|
||||
|
||||
// F - B
|
||||
c2[0] = c[0] - c[3];
|
||||
c2[1] = c[1] - c[4];
|
||||
c2[2] = c[2] - c[5];
|
||||
|
||||
a1 = ddot(3, (double*)c1, 1, (double*)c2, 1);
|
||||
a2 = dnrm2(3, c2, 1);
|
||||
alpha = a1/(a2*a2);
|
||||
alpha_lt = ALPHA_TAU*alpha + (1-ALPHA_TAU)*alpha_lt;
|
||||
delta_alpha = fabs(1 - alpha/alpha_lt);
|
||||
alpha = alpha_lt;
|
||||
is_valid = 1;
|
||||
iteration++;
|
||||
}
|
||||
|
||||
if (!is_valid && !iteration)
|
||||
continue;
|
||||
|
||||
// If we have a solution from previous iteration
|
||||
if (!is_valid && iteration)
|
||||
memcpy(c, c_last, 6*sizeof(double));
|
||||
|
||||
c1[0] = c[0] - colorMean_f[0];
|
||||
c1[1] = c[1] - colorMean_f[1];
|
||||
c1[2] = c[2] - colorMean_f[2];
|
||||
c2[0] = c[3] - colorMean_b[0];
|
||||
c2[1] = c[4] - colorMean_b[1];
|
||||
c2[2] = c[5] - colorMean_b[2];
|
||||
|
||||
// L_F = -(color_F-color_mean_F)'*inv_C_F*(color_F-color_mean_F)/2;
|
||||
dgemv('N', 3, 3, 0.5, (double*)cov_f, 3, (double*)c1, 1, 0.0, t, 1);
|
||||
L_f = -ddot(3, (double*)c1, 1, (double*)t, 1);
|
||||
|
||||
// L_B = -(color_B-color_mean_B)'*inv_C_B*(color_B-color_mean_B)/2;
|
||||
dgemv('N', 3, 3, 0.5, (double*)cov_b, 3, (double*)c2, 1, 0.0, t, 1);
|
||||
L_b = -ddot(3, (double*)c2, 1, (double*)t, 1);
|
||||
|
||||
c1[0] = colorComp[0] - (alpha*c[0] + (1-alpha)*c[3]);
|
||||
c1[1] = colorComp[1] - (alpha*c[1] + (1-alpha)*c[4]);
|
||||
c1[2] = colorComp[2] - (alpha*c[2] + (1-alpha)*c[5]);
|
||||
|
||||
// Likelihood(k) = -norm(color_C-a*color_F-(1-a)*color_B)^2/sigma_c^2 + L_F + L_B;
|
||||
L_sol = dnrm2(3, c1, 1);
|
||||
L_sol = -(L_sol*L_sol)*s2_i + L_f + L_b;
|
||||
|
||||
if (L_sol > pObj->L)
|
||||
{
|
||||
pObj->L = L_sol;
|
||||
pObj->P = pow(10,L_sol);
|
||||
pObj->alpha = alpha;
|
||||
memcpy(pObj->color_f, &c[0], sizeof(color_vector_t));
|
||||
memcpy(pObj->color_b, &c[3], sizeof(color_vector_t));
|
||||
|
||||
pObj->alpha_c = smin(smax(alpha,0),1);
|
||||
|
||||
pObj->color_f_c[0] = smin(smax(pObj->color_f[0],0),1);
|
||||
pObj->color_f_c[1] = smin(smax(pObj->color_f[1],0),1);
|
||||
pObj->color_f_c[2] = smin(smax(pObj->color_f[2],0),1);
|
||||
|
||||
pObj->color_b_c[0] = smin(smax(pObj->color_b[0],0),1);
|
||||
pObj->color_b_c[1] = smin(smax(pObj->color_b[1],0),1);
|
||||
pObj->color_b_c[2] = smin(smax(pObj->color_b[2],0),1);
|
||||
|
||||
pObj->solver_rounds = iteration;
|
||||
}
|
||||
|
||||
#ifdef MATTE_DEBUG
|
||||
PrintMatrix("Mean_f=", (double*)colorMean_f, 1, 3);
|
||||
PrintMatrix("color_f=", (double*)&c[0], 1, 3);
|
||||
PrintMatrix("Mean_b=", (double*)colorMean_b, 1, 3);
|
||||
PrintMatrix("color_b=", (double*)&c[3], 1, 3);
|
||||
printf("Alpha=%g\n", alpha);
|
||||
printf("P=%g\n", pow(10,L_sol));
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
// Loop end
|
||||
// ----------------------------
|
||||
if (pObj->solver_rounds == 0)
|
||||
fprintf(stderr, "MatteEstimate(): No solution found!\n");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int MatteProcess(matte_t *pObj)
|
||||
{
|
||||
|
||||
int i, num_fore, num_back, num_colors_f, num_colors_b;
|
||||
int max_npixel, num_computed;
|
||||
pxl_id_t pid_u, pid_closest_f, pid_closest_b, *pPid_f, *pPid_b;
|
||||
pxl_id_t *pCalcSet = pObj->pCalcSet;
|
||||
set_data_t *pCompSet = &pObj->comp_set;
|
||||
pixel_t *pPixel = pCompSet->pPixel;
|
||||
color_vector_t *pColor_set;
|
||||
double *pW_f, *pW_b, *pAlpha_f, *pAlpha_b, *pLikely, radius_f, radius_b;
|
||||
color_vector_t colorComp, *pColorComp, *pColor_f, *pColor_b;
|
||||
matte_sol_t sol;
|
||||
char filename[1024];
|
||||
double progress, last_progress;
|
||||
|
||||
last_progress = -REPORT_INTERVAL;
|
||||
|
||||
if(pCompSet->num_fore > pCompSet->num_back)
|
||||
|
||||
max_npixel = pCompSet->num_fore + pCompSet->num_unknown;
|
||||
else
|
||||
max_npixel = pCompSet->num_back + pCompSet->num_unknown;
|
||||
|
||||
|
||||
colorquant_t clob_f, clob_b;
|
||||
codebook_t cb_f, cb_b;
|
||||
color_stat_t colorStat_f, colorStat_b;
|
||||
|
||||
ColorQuant_Init(&clob_f, max_npixel, MAX_COLORS);
|
||||
ColorQuant_Init(&clob_b, max_npixel, MAX_COLORS);
|
||||
CodebookAlloc(&cb_f, max_npixel, MAX_COLORS);
|
||||
CodebookAlloc(&cb_b, max_npixel, MAX_COLORS);
|
||||
|
||||
pPid_f = (pxl_id_t*)malloc(max_npixel*sizeof(pxl_id_t));
|
||||
pPid_b = (pxl_id_t*)malloc(max_npixel*sizeof(pxl_id_t));
|
||||
|
||||
pW_f = (double*)malloc(max_npixel*sizeof(double));
|
||||
pW_b = (double*)malloc(max_npixel*sizeof(double));
|
||||
|
||||
pColor_set = (color_vector_t*)malloc(max_npixel*sizeof(color_vector_t));
|
||||
|
||||
ColorStatInit(&colorStat_f, max_npixel, MAX_COLORS, pixel_state_foreground);
|
||||
ColorStatInit(&colorStat_b, max_npixel, MAX_COLORS, pixel_state_background);
|
||||
|
||||
pColor_f = (color_vector_t*)pObj->im_f.pColor_data;
|
||||
pColor_b = (color_vector_t*)pObj->im_b.pColor_data;
|
||||
pColorComp = pColor_f;
|
||||
pAlpha_f = (double*)pObj->im_alpha_f.pColor_data;
|
||||
pAlpha_b = (double*)pObj->im_alpha_b.pColor_data;
|
||||
pLikely = (double*)pObj->im_P.pColor_data;
|
||||
|
||||
num_computed = 0;
|
||||
for(i=0; i < pCompSet->num_unknown; i++)
|
||||
{
|
||||
|
||||
pid_u = pCalcSet[i];
|
||||
|
||||
if(pixel_state_unknown != pObj->comp_set.pPixel[pid_u].state)
|
||||
{
|
||||
fprintf(stderr,"Pixel #%d is not unknown\n", i);
|
||||
}
|
||||
|
||||
memcpy(colorComp, pColorComp[pid_u], sizeof(color_vector_t));
|
||||
|
||||
pid_closest_f = pPixel[pid_u].id_closest_f;
|
||||
pid_closest_b = pPixel[pid_u].id_closest_b;
|
||||
|
||||
// Get foreground set and quantize
|
||||
radius_f = RADIUS_MIN;
|
||||
|
||||
#ifdef USE_SLIDING_WINDOW
|
||||
num_fore = MatteGetSet(pCompSet, pPid_f, pid_u, pAlpha_f, &radius_f, pixel_state_foreground | pixel_state_computed);
|
||||
#else
|
||||
num_fore = MatteGetSet(pCompSet, pPid_f, pid_closest_f, pAlpha_f, &radius_f, pixel_state_foreground | pixel_state_computed);
|
||||
#endif
|
||||
MatteGetColor(pPid_f, pColor_f, pColor_set, num_fore);
|
||||
|
||||
num_colors_f = ColorQuant(&clob_f, &cb_f, pColor_set, 3, num_fore, MAX_COLORS, LAMBDA_THRESH);
|
||||
|
||||
MatteComputeWeights(pCompSet, pid_u, pPid_f, pAlpha_f, pW_f, num_fore, radius_f, pixel_state_foreground);
|
||||
ColorStatProcess(pObj, &colorStat_f, &cb_f, pColor_set, num_fore, pW_f, SIGMA_C);
|
||||
|
||||
// Get background set and quantize
|
||||
radius_b = RADIUS_MIN;
|
||||
|
||||
#ifdef USE_SLIDING_WINDOW
|
||||
num_back = MatteGetSet(pCompSet, pPid_b, pid_u, pAlpha_b, &radius_b, pixel_state_background | pixel_state_computed);
|
||||
#else
|
||||
num_back = MatteGetSet(pCompSet, pPid_b, pid_closest_b, pAlpha_b, &radius_b, pixel_state_background | pixel_state_computed);
|
||||
#endif
|
||||
MatteGetColor(pPid_b, pColor_b, pColor_set, num_back);
|
||||
|
||||
num_colors_b = ColorQuant(&clob_b, &cb_b, pColor_set, 3, num_back, MAX_COLORS, LAMBDA_THRESH);
|
||||
|
||||
MatteComputeWeights(pCompSet, pid_u, pPid_b, pAlpha_b, pW_b, num_back, radius_b, pixel_state_background);
|
||||
ColorStatProcess(pObj, &colorStat_b, &cb_b, pColor_set, num_back, pW_b, SIGMA_C);
|
||||
|
||||
// Find solution
|
||||
MatteEstimate(&sol, colorComp, &colorStat_f, &colorStat_b, SIGMA_C);
|
||||
|
||||
#ifdef MATTE_DEBUG
|
||||
printf("\n------------------------------------------\n");
|
||||
printf("Unknown Pixel #%d\n", i);
|
||||
PrintMatrix("color_c=", (double*)colorComp, 3, 1);
|
||||
PrintMatrix("color_f=", (double*)sol.color_f, 3, 1);
|
||||
PrintMatrix("color_b=", (double*)sol.color_b, 3, 1);
|
||||
printf("Alpha= %f\n", sol.alpha);
|
||||
printf("P_sol=%f\n", sol.P);
|
||||
printf("Number of solver round=%d\n",sol.solver_rounds);
|
||||
printf("Number of colors int foreground statistic=%d\n",colorStat_f.num_colors);
|
||||
printf("Number of colors int background statistic=%d\n",colorStat_b.num_colors);
|
||||
#endif
|
||||
memcpy(pColor_f[pid_u], sol.color_f_c, sizeof(color_vector_t));
|
||||
memcpy(pColor_b[pid_u], sol.color_b_c, sizeof(color_vector_t));
|
||||
pAlpha_f[pid_u] = sol.alpha_c;
|
||||
pAlpha_b[pid_u] = 1-sol.alpha_c;
|
||||
pLikely[pid_u] = sol.P;
|
||||
|
||||
// Label unknown pixel as computed
|
||||
if (sol.solver_rounds > 0)
|
||||
{
|
||||
pObj->comp_set.pPixel[pid_u].state = pixel_state_computed;
|
||||
num_computed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown Pixel #%d(ID=%d) not computed.\n", i, pid_u);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_ANIMATION
|
||||
sprintf(filename, "ani/%s_alpha_%5.5d.tif",pObj->name,i);
|
||||
ImageSaveTiff(&pObj->im_alpha_f, NULL, filename);
|
||||
sprintf(filename, "ani/%s_est_fore_%5.5d.tif",pObj->name, i);
|
||||
ImageSaveTiff(&pObj->im_f, NULL, filename);
|
||||
sprintf(filename, "ani/%s_est_back_%5.5d.tif",pObj->name, i);
|
||||
ImageSaveTiff(&pObj->im_b, NULL, filename);
|
||||
#endif
|
||||
// Output progress
|
||||
progress = 100*(double)num_computed/(pCompSet->num_unknown-1);
|
||||
|
||||
if ((progress-last_progress) >= REPORT_INTERVAL)
|
||||
{
|
||||
printf("\r%d %% computed...", (int)progress);
|
||||
last_progress = progress;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("\r%d %% computed. \n", (int)progress);
|
||||
printf("%d of %d pixels computed.\n\n", num_computed, pCompSet->num_unknown);
|
||||
|
||||
sprintf(filename, "%s_alpha.tif", pObj->name);
|
||||
ImageSaveTiff(&pObj->im_alpha_f, NULL, filename);
|
||||
sprintf(filename, "%s_fore.tif",pObj->name);
|
||||
ImageSaveTiff(&pObj->im_f, pAlpha_f, filename);
|
||||
sprintf(filename, "%s_back.tif",pObj->name);
|
||||
ImageSaveTiff(&pObj->im_b, pAlpha_b, filename);
|
||||
sprintf(filename, "%s_est_fore.tif",pObj->name);
|
||||
ImageSaveTiff(&pObj->im_f, NULL, filename);
|
||||
sprintf(filename, "%s_est_back.tif",pObj->name);
|
||||
ImageSaveTiff(&pObj->im_b, NULL, filename);
|
||||
sprintf(filename, "%s_p.tif",pObj->name);
|
||||
ImageSaveTiff(&pObj->im_P, NULL, filename);
|
||||
|
||||
ImageFree(&pObj->im_f);
|
||||
ImageFree(&pObj->im_b);
|
||||
ImageFree(&pObj->im_alpha_f);
|
||||
ImageFree(&pObj->im_alpha_b);
|
||||
ImageFree(&pObj->im_P);
|
||||
|
||||
CodebookFree(&cb_f);
|
||||
CodebookFree(&cb_b);
|
||||
|
||||
ColorQuant_Free(&clob_f);
|
||||
ColorQuant_Free(&clob_b);
|
||||
|
||||
ColorStatFree(&colorStat_f);
|
||||
ColorStatFree(&colorStat_b);
|
||||
|
||||
free(pPid_f);
|
||||
free(pPid_b);
|
||||
free(pW_f);
|
||||
free(pW_b);
|
||||
free(pColor_set);
|
||||
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,66 @@
|
||||
// ------------------------------------------------------------
|
||||
// matte.h
|
||||
//
|
||||
// Reading writing tiff images
|
||||
//
|
||||
// 12.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#ifndef MATTE_H
|
||||
#define MATTE_H
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "imageio.h"
|
||||
#include "pixel.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
typedef struct _matte_settings_t
|
||||
{
|
||||
int debug;
|
||||
int use_lab;
|
||||
int use_computed_pixel;
|
||||
int use_sliding_window_computing; // instead of clustering fore and back separately
|
||||
int use_constant_color_background;
|
||||
double sigma_c, sigma_gf;
|
||||
int min_set_size;
|
||||
|
||||
} matte_settings_t;
|
||||
|
||||
typedef struct _matte_t
|
||||
{
|
||||
char name[256];
|
||||
image_t im_f, im_b, im_alpha_f, im_alpha_b, im_P;
|
||||
double *pL, *pWork;
|
||||
set_data_t comp_set;
|
||||
pxl_id_t *pCalcSet;
|
||||
matte_settings_t settings;
|
||||
|
||||
} matte_t;
|
||||
|
||||
typedef struct _color_stat_t
|
||||
{
|
||||
color_vector_t *pColor_mean;
|
||||
color_matrix_t *pCov_inv;
|
||||
double *pWork;
|
||||
int work_size, work_size_svd, work_size_inv;
|
||||
int num_colors;
|
||||
UINT32 type;
|
||||
|
||||
} color_stat_t;
|
||||
|
||||
typedef struct _matte_sol_t
|
||||
{
|
||||
double L, P;
|
||||
double alpha, alpha_c;
|
||||
color_vector_t color_f, color_b, color_f_c, color_b_c;
|
||||
int solver_rounds;
|
||||
|
||||
} matte_sol_t;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void MatteInit(matte_t *pObj, image_t *pComposite, image_t *pTrimap, char *name, matte_settings_t *pSettings);
|
||||
int MatteGetSet(set_data_t *pObj, pxl_id_t *pPid, pxl_id_t pid, double *pAlpha, double *radius, UINT32 types);
|
||||
int MatteGetColor(pxl_id_t *pPid, color_vector_t *pSrc, color_vector_t *pDst, int num_pixel);
|
||||
int MatteGetData(pxl_id_t *pPid, double *pSrc, double *pDst, int num_pixel);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#endif // MATTE_H
|
||||
@@ -0,0 +1,82 @@
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// mlio.c
|
||||
// Input/output for Matlab matrices
|
||||
// -----------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mlio.h"
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
int mlio_open(mlio_t *pObj, char *pName, unsigned mode)
|
||||
{
|
||||
|
||||
pObj->io_mode = mode;
|
||||
|
||||
if (mode == MLIO_READ)
|
||||
{
|
||||
pObj->pFile = fopen(pName, "rb");
|
||||
|
||||
// Read input file
|
||||
if (!pObj->pFile)
|
||||
{
|
||||
fprintf(stderr,"Unable to open input file %s\n", pName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Header
|
||||
fread(&pObj->hdr_file.version, 1, sizeof(unsigned), pObj->pFile);
|
||||
fscanf(pObj->pFile, "%s", pObj->hdr_file.prec_typename);
|
||||
fseek(pObj->pFile, 1, SEEK_CUR);
|
||||
fread(&pObj->hdr_data, 1, sizeof(data_hdr_t), pObj->pFile);
|
||||
printf("Rows=%d, Columns=%d, File size=%d bytes\n", pObj->hdr_data.num_row, pObj->hdr_data.num_col, pObj->hdr_data.size);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pObj->pFile = fopen(pName, "wb");
|
||||
|
||||
// Write output file
|
||||
if (!pObj->pFile)
|
||||
{
|
||||
fprintf(stderr,"Unable to open output file %s\n", pName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int mlio_close(mlio_t *pObj)
|
||||
{
|
||||
return fclose(pObj->pFile);
|
||||
}
|
||||
|
||||
int mlio_read(mlio_t *pObj, double *pData)
|
||||
{
|
||||
// Read data
|
||||
fread(pData, pObj->hdr_data.num_row*pObj->hdr_data.num_col, sizeof(double), pObj->pFile);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int mlio_write(mlio_t *pObj, double *pData, unsigned num_rows, unsigned num_cols)
|
||||
{
|
||||
|
||||
pObj->hdr_data.num_row = num_rows;
|
||||
pObj->hdr_data.num_col = num_cols;
|
||||
|
||||
// Header
|
||||
fwrite(&pObj->hdr_file.version, 1, sizeof(unsigned), pObj->pFile);
|
||||
fprintf(pObj->pFile, "%s\r", pObj->hdr_file.prec_typename);
|
||||
fwrite(&pObj->hdr_data, 1, sizeof(data_hdr_t), pObj->pFile);
|
||||
|
||||
// Write data
|
||||
fwrite(pData, pObj->hdr_data.num_row*pObj->hdr_data.num_col, sizeof(double), pObj->pFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,46 @@
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// mlio.h
|
||||
// Input/output for Matlab matrices
|
||||
// 26.02.2005, J. Ahrensfeld
|
||||
//
|
||||
// -----------------------------------------------------------------------------------------
|
||||
#ifndef MLIO_H
|
||||
#define MLIO_H
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
#define MLIO_READ 1
|
||||
#define MLIO_WRITE 2
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
typedef struct _data_hdr_t
|
||||
{
|
||||
unsigned num_row, num_col;
|
||||
unsigned size;
|
||||
|
||||
} data_hdr_t;
|
||||
|
||||
typedef struct _file_hdr_t
|
||||
{
|
||||
unsigned version;
|
||||
char prec_typename[32];
|
||||
|
||||
} file_hdr_t;
|
||||
|
||||
typedef struct _mlio_t
|
||||
{
|
||||
FILE *pFile;
|
||||
unsigned io_mode;
|
||||
|
||||
file_hdr_t hdr_file;
|
||||
data_hdr_t hdr_data;
|
||||
} mlio_t;
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
int mlio_open(mlio_t *pObj, char *pName, unsigned mode);
|
||||
int mlio_close(mlio_t *pObj);
|
||||
int mlio_read(mlio_t *pObj, double *pData);
|
||||
int mlio_write(mlio_t *pObj, double *pData, unsigned num_rows, unsigned num_cols);
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
#endif //MLIO_H
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// ------------------------------------------------------------
|
||||
// imageio.h
|
||||
//
|
||||
// Reading writing tiff images
|
||||
//
|
||||
// 12.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#ifndef MTYPES_H
|
||||
#define MTYPES_H
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define COMP_RED 0
|
||||
#define COMP_GREEN 1
|
||||
#define COMP_BLUE 2
|
||||
#define COMP_L 0
|
||||
#define COMP_A 1
|
||||
#define COMP_B 2
|
||||
#define COORD_X 0
|
||||
#define COORD_Y 1
|
||||
|
||||
typedef unsigned int UINT32;
|
||||
typedef signed int INT32;
|
||||
typedef unsigned short UINT16;
|
||||
typedef signed short INT16;
|
||||
typedef unsigned char UINT8;
|
||||
typedef signed char INT8;
|
||||
|
||||
typedef UINT32 pxl_id_t;
|
||||
|
||||
typedef int pos_t[2];
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#endif // MTYPES_H
|
||||
@@ -0,0 +1,220 @@
|
||||
// ------------------------------------------------------------
|
||||
// mutil.c
|
||||
// Matrix utilities
|
||||
// 5.3.2005, J.Ahrensfeld
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lapack_cwrap.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
double lp_work_buf[1024] = {0};
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void Eye(double *pI, double value, int N)
|
||||
{
|
||||
int len;
|
||||
|
||||
memset(pI, 0, N*N*sizeof(double));
|
||||
|
||||
len = 0;
|
||||
|
||||
while(len < N*N)
|
||||
{
|
||||
pI[len] = value;
|
||||
len += (N+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void RandMat(double *pA, int N)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < N; i++)
|
||||
pA[i] = 2.0*(0.5 - (double)rand()/RAND_MAX);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void IncMat(double *pA, int nRow, int nCol, char order)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
if (order == 'R')
|
||||
{
|
||||
k = 1;
|
||||
for(i=0; i < nCol; i++)
|
||||
for(j=0; j < nRow; j++)
|
||||
pA[i*nRow+j] = (double)k++;
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 1;
|
||||
for(i=0; i < nRow; i++)
|
||||
for(j=0; j < nCol; j++)
|
||||
pA[j*nRow+i] = (double)k++;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void CopyTrans(double *pA, double *pAT, int nRow, int nCol)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(i=0; i < nRow; i++)
|
||||
for(j=0; j < nCol; j++)
|
||||
pAT[j+i*nCol] = pA[j*nRow+i];
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void GetDiag(double *pA, double *pY, int N)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < N; i++)
|
||||
pY[i] = pA[i*N+i];
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void MakeDiag(double *pD, double *pX, int N)
|
||||
{
|
||||
int len;
|
||||
|
||||
memset(pD, 0, N*N*sizeof(double));
|
||||
|
||||
len = 0;
|
||||
while(len < N*N)
|
||||
{
|
||||
pD[len] = *(pX++);
|
||||
len += (N+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void PrintMatrix(char *pStr, double *A, int num_row, int num_col)
|
||||
{
|
||||
int i, j;
|
||||
double v;
|
||||
|
||||
printf("%s\n",pStr);
|
||||
for (i=0; i<num_row; i++)
|
||||
{
|
||||
for (j=0; j<num_col; j++)
|
||||
{
|
||||
v = A[j*num_row+i];
|
||||
printf ("%5.5g ", v);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void PrintMatrixSym(char *pStr, double *A, int num_row, int num_col, char uplo)
|
||||
{
|
||||
int i, j;
|
||||
double v;
|
||||
|
||||
printf("%s\n",pStr);
|
||||
for (i=0; i<num_row; i++)
|
||||
{
|
||||
for (j=0; j<num_col; j++)
|
||||
{
|
||||
v = A[j*num_row+i];
|
||||
printf ("%5.5g ", v);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
double smin(double v1, double v2)
|
||||
{
|
||||
if (v1 < v2)
|
||||
return v1;
|
||||
|
||||
return v2;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
double smax(double v1, double v2)
|
||||
{
|
||||
if (v1 > v2)
|
||||
return v1;
|
||||
|
||||
return v2;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void vsum(double *pX, double *pY, int lda, int N)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j=0; j < lda; j++)
|
||||
pY[j] = *(pX++);
|
||||
|
||||
for(i=1; i < N; i++)
|
||||
for (j=0; j < lda; j++)
|
||||
pY[j] += *(pX++);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void GetPrincipleEigenVector(double *pA, double *pV, int lda)
|
||||
{
|
||||
double max_x;
|
||||
int max_i, i;
|
||||
|
||||
max_x = pV[0];
|
||||
max_i = 0;
|
||||
|
||||
for (i=1; i < lda; i++)
|
||||
{
|
||||
if(pV[i] > max_x)
|
||||
{
|
||||
max_x = pV[0];
|
||||
max_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i < lda; i++)
|
||||
pV[i] = pA[max_i*lda + i];
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
double dnrm(int N, int M, double *A, char mode)
|
||||
{
|
||||
int i;
|
||||
double maxval, val;
|
||||
|
||||
maxval = 0;
|
||||
if (mode == '1')
|
||||
{
|
||||
for (i=0; i < N*M; i += N)
|
||||
{
|
||||
val = dasum(N, &A[i], 1);
|
||||
if (val > maxval)
|
||||
maxval = val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < N; i++)
|
||||
{
|
||||
val = dasum(M, &A[i], N);
|
||||
if (val > maxval)
|
||||
maxval = val;
|
||||
}
|
||||
}
|
||||
|
||||
return maxval;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// ------------------------------------------------------------
|
||||
// mutil.h
|
||||
// Matrix utilities
|
||||
// 5.3.2005, J.Ahrensfeld
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
#ifndef MUTIL_H
|
||||
#define MUTIL_H
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
void RandMat(double *pA, int N);
|
||||
void IncMat(double *pA, int nRow, int nCol, char order);
|
||||
void CopyTrans(double *pA, double *pAT, int nRow, int nCol);
|
||||
void Eye(double *pI, double value, int N);
|
||||
void Diag(double *pA, double *pY, int N);
|
||||
void MakeDiag(double *pD, double *pX, int N);
|
||||
void PrintMatrix(char *pStr, double *A, int num_row, int num_col);
|
||||
double smin(double v1, double v2);
|
||||
double smax(double v1, double v2);
|
||||
void vsum(double *pX, double *pY, int lda, int N);
|
||||
void GetPrincipleEigenVector(double *pA, double *pV, int lda);
|
||||
double dnrm(int N, int M, double *A, char mode);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#endif //MUTIL_H
|
||||
@@ -0,0 +1,413 @@
|
||||
// ------------------------------------------------------------
|
||||
// pixel.c
|
||||
//
|
||||
// Retrieving pixels in image and maintaining pixel attributes
|
||||
//
|
||||
// 13.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include "bintree.h"
|
||||
#include "mutil.h"
|
||||
#include "lapack_cwrap.h"
|
||||
#include "clob.h"
|
||||
#include "pixel.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define CALCSET_RADIUS_INITIAL 5
|
||||
#define CALCSET_RADIUS_INCREMENT 1.0
|
||||
#define CALCSET_DISTMIN_INITIAL 1E12
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void SetInit(set_data_t *pObj, int num_row, int num_col)
|
||||
{
|
||||
int i, x, y;
|
||||
|
||||
pObj->num_row = num_row;
|
||||
pObj->num_col = num_col;
|
||||
pObj->num_pixel = num_row*num_col;
|
||||
|
||||
pObj->pPixel = (pixel_t*)malloc(pObj->num_pixel*sizeof(pixel_t));
|
||||
|
||||
x = y = 0;
|
||||
for (i=0; i < pObj->num_pixel; i++)
|
||||
{
|
||||
pObj->pPixel[i].id_this = i;
|
||||
pObj->pPixel[i].state = 0;
|
||||
pObj->pPixel[i].raster_coord[0] = x++;
|
||||
pObj->pPixel[i].raster_coord[1] = y;
|
||||
if (x >= num_col)
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void SetFree(set_data_t *pObj)
|
||||
{
|
||||
if (!pObj)
|
||||
return;
|
||||
|
||||
if (pObj->pPixel)
|
||||
free(pObj->pPixel);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void PixelStateInit(set_data_t *pObj, image_t *pTrimap_image)
|
||||
{
|
||||
int i, k;
|
||||
double *pTrimap = (double*)pTrimap_image->pColor_data;
|
||||
|
||||
k = pTrimap_image->num_ch;
|
||||
|
||||
pObj->num_fore = 0;
|
||||
pObj->num_back = 0;
|
||||
pObj->num_unknown = 0;
|
||||
|
||||
for (i=0; i < pObj->num_pixel; i++)
|
||||
{
|
||||
pObj->pPixel[i].state = pixel_state_background;
|
||||
if(pTrimap[k*i] > 0.7)
|
||||
{
|
||||
pObj->pPixel[i].state = pixel_state_foreground;
|
||||
pObj->num_fore++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pTrimap[k*i] > 0.2)
|
||||
{
|
||||
pObj->pPixel[i].state = pixel_state_unknown;
|
||||
pObj->num_unknown++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pObj->num_back = pObj->num_pixel - (pObj->num_fore + pObj->num_unknown);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int GetCropSet(set_data_t *pObj, int *pCrop, pos_t center, pos_t rect_size, UINT32 select_state)
|
||||
{
|
||||
|
||||
int i, j, x, y, min_x, min_y, max_x, max_y;
|
||||
|
||||
if (!(rect_size[COORD_X]%2))
|
||||
rect_size[COORD_X]++;
|
||||
|
||||
if (!(rect_size[COORD_Y]%2))
|
||||
rect_size[COORD_Y]++;
|
||||
|
||||
min_x = center[COORD_X]-(rect_size[COORD_X]-1)/2;
|
||||
if (min_x < 0)
|
||||
min_x = 0;
|
||||
|
||||
max_x = center[COORD_X]+(rect_size[COORD_X]-1)/2;
|
||||
if (max_x >= pObj->num_col)
|
||||
max_x = pObj->num_col-1;
|
||||
|
||||
min_y = center[COORD_Y]-(rect_size[COORD_Y]-1)/2;
|
||||
if (min_y < 0)
|
||||
min_y = 0;
|
||||
|
||||
max_y = center[COORD_Y]+(rect_size[COORD_Y]-1)/2;
|
||||
if (max_y >= pObj->num_row)
|
||||
max_y = pObj->num_row-1;
|
||||
|
||||
|
||||
i = 0;
|
||||
if (select_state == pixel_state_all)
|
||||
{
|
||||
for (y=min_y; y <= max_y; y++)
|
||||
{
|
||||
for (x=min_x; x <= max_x; x++)
|
||||
{
|
||||
pCrop[i] = y*pObj->num_col + x;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y=min_y; y <= max_y; y++)
|
||||
{
|
||||
for (x=min_x; x <= max_x; x++)
|
||||
{
|
||||
j = y*pObj->num_col + x;
|
||||
if (pObj->pPixel[j].state & select_state)
|
||||
{
|
||||
pCrop[i] = j;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int GetCircleSet(set_data_t *pObj, int *pCrop, pos_t center, double radius, UINT32 select_state)
|
||||
{
|
||||
int i, j, num_found;
|
||||
|
||||
double distance, diff[2];
|
||||
pos_t rect_size;
|
||||
|
||||
rect_size[0] = 2*(int)radius+1;
|
||||
rect_size[1] = 2*(int)radius+1;
|
||||
|
||||
num_found = GetCropSet(pObj, pCrop, center, rect_size, select_state);
|
||||
|
||||
j=0;
|
||||
for (i=0; i < num_found; i++)
|
||||
{
|
||||
diff[0] = (double)(center[0] - pObj->pPixel[pCrop[i]].raster_coord[0]);
|
||||
diff[1] = (double)(center[1] - pObj->pPixel[pCrop[i]].raster_coord[1]);
|
||||
distance = dnrm2(2, diff, 1);
|
||||
|
||||
if(distance < radius)
|
||||
{
|
||||
pCrop[j++] = pCrop[i];
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int GetSetByState(set_data_t *pObj, pxl_id_t *pSet, UINT32 select_state)
|
||||
{
|
||||
|
||||
UINT32 i, j;
|
||||
|
||||
j=0;
|
||||
if (pSet)
|
||||
{
|
||||
for (i=0; i < pObj->num_pixel; i++)
|
||||
{
|
||||
|
||||
if (pObj->pPixel[i].state & select_state)
|
||||
{
|
||||
pSet[j] = pObj->pPixel[i].id_this;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Query only
|
||||
{
|
||||
for (i=0; i < pObj->num_pixel; i++)
|
||||
{
|
||||
|
||||
if (pObj->pPixel[i].state & select_state)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Calcset set stuff
|
||||
// Creates optimal computing order for unknown pixels
|
||||
// ------------------------------------------------------------
|
||||
int ComputeDistanceMap(set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown)
|
||||
{
|
||||
int i, j, s, t, num_fore, num_back;
|
||||
pxl_id_t *pSet_f, *pSet_b, id_min;
|
||||
double radius, distance, distance_min, diff[2];
|
||||
pos_t curr_pos;
|
||||
node_t *node;
|
||||
bintree_t bst;
|
||||
|
||||
void *data;
|
||||
|
||||
pSet_f = (pxl_id_t*)malloc(pObj->num_fore*sizeof(pxl_id_t));
|
||||
pSet_b = (pxl_id_t*)malloc(pObj->num_back*sizeof(pxl_id_t));
|
||||
|
||||
for (i=0; i < num_unknown; i++)
|
||||
{
|
||||
s = pSet_unknown[i];
|
||||
curr_pos[0] = pObj->pPixel[s].raster_coord[0];
|
||||
curr_pos[1] = pObj->pPixel[s].raster_coord[1];
|
||||
|
||||
radius = CALCSET_RADIUS_INITIAL;
|
||||
do
|
||||
{
|
||||
num_fore = GetCircleSet(pObj, pSet_f, curr_pos, radius, pixel_state_foreground);
|
||||
radius += CALCSET_RADIUS_INCREMENT;
|
||||
|
||||
} while (num_fore == 0);
|
||||
|
||||
radius = CALCSET_RADIUS_INITIAL;
|
||||
do
|
||||
{
|
||||
num_back = GetCircleSet(pObj, pSet_b, curr_pos, radius, pixel_state_background);
|
||||
radius += CALCSET_RADIUS_INCREMENT;
|
||||
|
||||
} while (num_back == 0);
|
||||
|
||||
bintree_init(&bst, num_fore);
|
||||
distance_min = CALCSET_DISTMIN_INITIAL;
|
||||
for (j=0; j < num_fore; j++)
|
||||
{
|
||||
t = pSet_f[j];
|
||||
diff[0] = (double)(curr_pos[0] - pObj->pPixel[t].raster_coord[0]);
|
||||
diff[1] = (double)(curr_pos[1] - pObj->pPixel[t].raster_coord[1]);
|
||||
|
||||
distance = diff[0]*diff[0] + diff[1]*diff[1];
|
||||
|
||||
data = (void*)t;
|
||||
bintree_insert(&bst, distance, data);
|
||||
|
||||
}
|
||||
node = bintree_GetNodeMin(&bst);
|
||||
id_min = (int)node->pData;
|
||||
distance_min = node->value;
|
||||
pObj->pPixel[s].id_closest_f = id_min;
|
||||
pObj->pPixel[s].dist_closest_f = sqrt(distance_min);
|
||||
bintree_free(&bst);
|
||||
|
||||
bintree_init(&bst, num_back);
|
||||
distance_min = CALCSET_DISTMIN_INITIAL;
|
||||
for (j=0; j < num_back; j++)
|
||||
{
|
||||
t = pSet_b[j];
|
||||
diff[0] = (double)(curr_pos[0] - pObj->pPixel[t].raster_coord[0]);
|
||||
diff[1] = (double)(curr_pos[1] - pObj->pPixel[t].raster_coord[1]);
|
||||
|
||||
distance = diff[0]*diff[0] + diff[1]*diff[1];
|
||||
|
||||
data = (void*)t;
|
||||
bintree_insert(&bst, distance, data);
|
||||
|
||||
}
|
||||
node = bintree_GetNodeMin(&bst);
|
||||
|
||||
id_min = (int)node->pData;
|
||||
distance_min = node->value;
|
||||
pObj->pPixel[s].id_closest_b = id_min;
|
||||
pObj->pPixel[s].dist_closest_b = sqrt(distance_min);
|
||||
bintree_free(&bst);
|
||||
}
|
||||
|
||||
free(pSet_f);
|
||||
free(pSet_b);
|
||||
|
||||
return num_unknown;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int ComputeCalcSet(set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown)
|
||||
{
|
||||
int i, s;
|
||||
void *data;
|
||||
|
||||
double v[2], distance;
|
||||
bintree_t bst;
|
||||
node_t *node;
|
||||
|
||||
bintree_init(&bst, num_unknown);
|
||||
|
||||
for (i=0; i < num_unknown; i++)
|
||||
{
|
||||
s = pSet_unknown[i];
|
||||
v[0] = pObj->pPixel[s].dist_closest_f;
|
||||
v[1] = pObj->pPixel[s].dist_closest_b;
|
||||
|
||||
if (v[0] < v[1])
|
||||
distance = v[0];
|
||||
else
|
||||
distance = v[1];
|
||||
|
||||
data = (void*)s;
|
||||
bintree_insert(&bst, distance, data);
|
||||
}
|
||||
|
||||
i=0;
|
||||
do
|
||||
{
|
||||
node = bintree_GetNodeMin(&bst);
|
||||
s = (int)node->pData;
|
||||
pSet_unknown[i] = s;
|
||||
i++;
|
||||
|
||||
} while(bintree_node_remove(&bst, node));
|
||||
|
||||
bintree_free(&bst);
|
||||
|
||||
return i;
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
int SaveCalcSet(char *filename, set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown)
|
||||
{
|
||||
int i;
|
||||
pxl_id_t s;
|
||||
FILE *pFile;
|
||||
|
||||
pFile = fopen(filename, "wb");
|
||||
if (!pFile)
|
||||
{
|
||||
fprintf(stderr, "Unable to open %s\n",filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fwrite(&num_unknown, sizeof(int), 1, pFile);
|
||||
fwrite(pSet_unknown, sizeof(pxl_id_t), num_unknown, pFile);
|
||||
|
||||
for(i=0; i < num_unknown; i++)
|
||||
{
|
||||
s = pSet_unknown[i];
|
||||
fwrite(&pObj->pPixel[s], sizeof(pixel_t), 1, pFile);
|
||||
}
|
||||
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
int LoadCalcSet(char *filename, set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown)
|
||||
{
|
||||
int i, N;
|
||||
pxl_id_t s;
|
||||
FILE *pFile;
|
||||
|
||||
pFile = fopen(filename, "rb");
|
||||
if (!pFile)
|
||||
{
|
||||
fprintf(stderr, "Unable to open %s\n",filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread(&N, sizeof(int), 1, pFile);
|
||||
if (N != num_unknown)
|
||||
{
|
||||
fclose(pFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread(pSet_unknown, sizeof(pxl_id_t), num_unknown, pFile);
|
||||
|
||||
for(i=0; i < num_unknown; i++)
|
||||
{
|
||||
s = pSet_unknown[i];
|
||||
fread(&pObj->pPixel[s], sizeof(pixel_t), 1, pFile);
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
for(i=0; i < num_unknown; i++)
|
||||
{
|
||||
s = pSet_unknown[i];
|
||||
if(pObj->pPixel[s].state != pixel_state_unknown)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// ------------------------------------------------------------
|
||||
// pixel.h
|
||||
//
|
||||
// Reading writing tiff images
|
||||
//
|
||||
// 12.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#ifndef PIXEL_H
|
||||
#define PIXEL_H
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "imageio.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#define MAJOR_STATE_MASK 0x03
|
||||
|
||||
enum PixelState
|
||||
{
|
||||
pixel_state_all = 0,
|
||||
pixel_state_foreground = 1,
|
||||
pixel_state_background = 2,
|
||||
pixel_state_unknown = 4,
|
||||
pixel_state_computed = 8
|
||||
};
|
||||
|
||||
typedef struct _pixel_t
|
||||
{
|
||||
UINT32 state;
|
||||
|
||||
pxl_id_t id_this, id_closest_f, id_closest_b;
|
||||
pos_t raster_coord;
|
||||
double dist_closest_f, dist_closest_b;
|
||||
|
||||
} pixel_t;
|
||||
|
||||
typedef struct _set_data_t
|
||||
{
|
||||
UINT32 num_row, num_col, num_pixel, num_unknown, num_fore, num_back;
|
||||
pixel_t *pPixel;
|
||||
|
||||
} set_data_t;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void SetInit(set_data_t *pObj, int num_row, int num_col);
|
||||
void PixelStateInit(set_data_t *pObj, image_t *pTrimap_image);
|
||||
int GetCropSet(set_data_t *pObj, int *pCrop, pos_t center, pos_t rect_size, UINT32 select_state);
|
||||
int GetCircleSet(set_data_t *pObj, int *pCrop, pos_t center, double radius, UINT32 select_state);
|
||||
int GetSetByState(set_data_t *pObj, pxl_id_t *pSet, UINT32 select_state);
|
||||
int ComputeDistanceMap(set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown);
|
||||
int ComputeCalcSet(set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown);
|
||||
int SaveCalcSet(char *filename, set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown);
|
||||
int LoadCalcSet(char *filename, set_data_t *pObj, pxl_id_t *pSet_unknown, int num_unknown);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#endif // PIXEL_H
|
||||
@@ -0,0 +1,29 @@
|
||||
// ------------------------------------------------------------
|
||||
// tictoc.c
|
||||
//
|
||||
// Utility to measure timing
|
||||
//
|
||||
// 10.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include "tictoc.h"
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void Tic(struct _tictoc_t *pObj)
|
||||
{
|
||||
gettimeofday(&pObj->s, &pObj->tz);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void Toc(struct _tictoc_t *pObj)
|
||||
{
|
||||
gettimeofday(&pObj->e, &pObj->tz);
|
||||
printf("Operation takes %f milliseconds.\n", (double)((pObj->e.tv_sec - pObj->s.tv_sec)*1000) + (double)(pObj->e.tv_usec - pObj->s.tv_usec)/1000);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,24 @@
|
||||
// ------------------------------------------------------------
|
||||
// tictoc.h
|
||||
//
|
||||
// Utility to measure timing
|
||||
//
|
||||
// 10.03.2005, J.Ahrensfeld
|
||||
// ------------------------------------------------------------
|
||||
#ifndef TICTOC_H
|
||||
#define TICTOC_H
|
||||
|
||||
// ------------------------------------------------------------
|
||||
typedef struct _tictoc_t
|
||||
{
|
||||
struct timeval s, e;
|
||||
struct timezone tz;
|
||||
|
||||
} tictoc_t;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
void Tic(struct _tictoc_t *pObj);
|
||||
void Toc(struct _tictoc_t *pObj);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
#endif // TICTOC_H
|
||||
Reference in New Issue
Block a user