43 #define NUMORIENTATIONS 8
46 #define MU (GAMMA2/(2*NUMNEIGH*GAMMA1))
49 #ifndef DOXYGEN_SHOULD_SKIP_THIS
52 #define CMAT_YR (5.773502691896258e-1)
53 #define CMAT_YG (5.773502691896258e-1)
54 #define CMAT_YB (5.773502691896258e-1)
55 #define CMAT_UR (M_1_SQRT2)
57 #define CMAT_UB (-M_1_SQRT2)
58 #define CMAT_VR (4.08248290463863e-1)
59 #define CMAT_VG (-8.16496580927726e-1)
60 #define CMAT_VB (4.08248290463863e-1)
75 #define CCMAT_RR (CMAT_YR*CMAT_YR + CMAT_UR*CMAT_UR + CMAT_VR*CMAT_VR)
76 #define CCMAT_RG (CMAT_YR*CMAT_YG + CMAT_UR*CMAT_UG + CMAT_VR*CMAT_VG)
77 #define CCMAT_RB (CMAT_YR*CMAT_YB + CMAT_UR*CMAT_UB + CMAT_VR*CMAT_VB)
78 #define CCMAT_GR (CMAT_YG*CMAT_YR + CMAT_UG*CMAT_UR + CMAT_VG*CMAT_VR)
79 #define CCMAT_GG (CMAT_YG*CMAT_YG + CMAT_UG*CMAT_UG + CMAT_VG*CMAT_VG)
80 #define CCMAT_GB (CMAT_YG*CMAT_YB + CMAT_UG*CMAT_UB + CMAT_VG*CMAT_VB)
81 #define CCMAT_BR (CMAT_YB*CMAT_YR + CMAT_UB*CMAT_UR + CMAT_VB*CMAT_VR)
82 #define CCMAT_BG (CMAT_YB*CMAT_YG + CMAT_UB*CMAT_UG + CMAT_VB*CMAT_VG)
83 #define CCMAT_BB (CMAT_YB*CMAT_YB + CMAT_UB*CMAT_UB + CMAT_VB*CMAT_VB)
86 #define UR_(A) ((float)A(CCMAT_RR + MU, CCMAT_RG, CCMAT_RB, \
87 CCMAT_GR, CCMAT_GG, CCMAT_GB, \
88 CCMAT_BR, CCMAT_BG, CCMAT_BB))
89 #define UG_(A) ((float)A(CCMAT_RR, CCMAT_RG, CCMAT_RB, \
90 CCMAT_GR, CCMAT_GG + MU, CCMAT_GB, \
91 CCMAT_BR, CCMAT_BG, CCMAT_BB))
92 #define UB_(A) ((float)A(CCMAT_RR, CCMAT_RG, CCMAT_RB, \
93 CCMAT_GR, CCMAT_GG, CCMAT_GB, \
94 CCMAT_BR, CCMAT_BG, CCMAT_BB + MU))
96 #define UINVR_RR (UR_(INV3X3_11))
97 #define UINVR_RG (UR_(INV3X3_12))
98 #define UINVR_RB (UR_(INV3X3_13))
99 #define UINVR_GR (UR_(INV3X3_21))
100 #define UINVR_GG (UR_(INV3X3_22))
101 #define UINVR_GB (UR_(INV3X3_23))
102 #define UINVR_BR (UR_(INV3X3_31))
103 #define UINVR_BG (UR_(INV3X3_32))
104 #define UINVR_BB (UR_(INV3X3_33))
106 #define UINVG_RR (UG_(INV3X3_11))
107 #define UINVG_RG (UG_(INV3X3_12))
108 #define UINVG_RB (UG_(INV3X3_13))
109 #define UINVG_GR (UG_(INV3X3_21))
110 #define UINVG_GG (UG_(INV3X3_22))
111 #define UINVG_GB (UG_(INV3X3_23))
112 #define UINVG_BR (UG_(INV3X3_31))
113 #define UINVG_BG (UG_(INV3X3_32))
114 #define UINVG_BB (UG_(INV3X3_33))
116 #define UINVB_RR (UB_(INV3X3_11))
117 #define UINVB_RG (UB_(INV3X3_12))
118 #define UINVB_RB (UB_(INV3X3_13))
119 #define UINVB_GR (UB_(INV3X3_21))
120 #define UINVB_GG (UB_(INV3X3_22))
121 #define UINVB_GB (UB_(INV3X3_23))
122 #define UINVB_BR (UB_(INV3X3_31))
123 #define UINVB_BG (UB_(INV3X3_32))
124 #define UINVB_BB (UB_(INV3X3_33))
144 static const int NeighX[
NUMNEIGH] = {1, 1, 0, -1, -1, -1, 0, 1};
146 static const int NeighY[
NUMNEIGH] = {0, -1, -1, -1, 0, 1, 1, 1};
148 static const int NeighAdj[
NUMNEIGH] = {4, 5, 6, 7, 0, 1, 2, 3};
153 {1, 0, 0, 0, 1, 0, 0, 0},
155 {2.0f/3, 1.0f/3, 0, 0, 2.0f/3, 1.0f/3, 0, 0},
157 {0, 1, 0, 0, 0, 1, 0, 0},
159 {0, 1.0f/3, 2.0f/3, 0, 0, 1.0f/3, 2.0f/3, 0},
161 {0, 0, 1, 0, 0, 0, 1, 0},
163 {0, 0, 2.0f/3, 1.0f/3, 0, 0, 2.0f/3, 1.0f/3},
165 {0, 0, 0, 1, 0, 0, 0, 1},
167 {2.0f/3, 0, 0, 1.0f/3, 2.0f/3, 0, 0, 1.0f/3}
189 return ((
float)CMAT_YR)*R + ((float)CMAT_YG)*G + ((float)CMAT_YB)*B;
199 return ((
float)CMAT_UR)*R + ((float)CMAT_UG)*G + ((float)CMAT_UB)*B;
209 return ((
float)CMAT_VR)*R + ((float)CMAT_VG)*G + ((float)CMAT_VB)*B;
260 const float *Image,
float (*Weight)[NUMNEIGH],
int Width,
int Height,
263 const int NumPixels = Width*Height;
264 const float *Red = Image;
265 const float *Green = Image + NumPixels;
266 const float *Blue = Image + 2*NumPixels;
267 float RedDiff, GreenDiff, BlueDiff;
269 int Channel, m, x, y, n, nOffset[
NUMNEIGH];
273 nOffset[n] = NeighX[n] + Width*NeighY[n];
275 for(y = 1; y < Height - 1; y++)
276 for(x = 1; x < Width - 1; x++)
282 RedDiff = Red[m] - Red[m + nOffset[n]];
283 GreenDiff = Green[m] - Green[m + nOffset[n]];
284 BlueDiff = Blue[m] - Blue[m + nOffset[n]];
287 Cu[n][0] = GetYComponent(RedDiff, GreenDiff, BlueDiff);
288 Cu[n][1] = GetUComponent(RedDiff, GreenDiff, BlueDiff);
289 Cu[n][2] = GetVComponent(RedDiff, GreenDiff, BlueDiff);
299 for(n = 0, dmag = 0; n <
NUMNEIGH; n++)
300 for(Channel = 1; Channel < 3; Channel++)
302 dnew[n][Channel] = Cu[n][Channel]
303 + d[m][n][Channel] - dtilde[m][n][Channel];
304 dmag += sqr(Weight[m][n]*d[m][n][Channel]);
310 for(Channel = 1; Channel < 3; Channel++)
311 dmag += sqr(Weight[m][n]*dnew[n][Channel]);
313 dmag = (float)sqrt(dmag);
316 for(Channel = 1; Channel < 3; Channel++)
319 dnew[n][Channel] *= dmag
320 /(Weight[m][n]*Weight[m][n]*Alpha/
GAMMA1 + dmag);
324 dtilde[m][n][Channel] += 2*dnew[n][Channel]
325 - d[m][n][Channel] - Cu[n][Channel];
327 d[m][n][Channel] = dnew[n][Channel];
334 for(n = 0, dmag = 0; n <
NUMNEIGH; n++)
336 dnew[n][0] = Cu[n][0] + d[m][n][0] - dtilde[m][n][0];
337 dmag += sqr(Weight[m][n]*d[m][n][0]);
342 dmag += sqr(Weight[m][n]*dnew[n][0]);
344 dmag = (float)sqrt(dmag);
348 dnew[n][0] *= dmag/(Weight[m][n]*Weight[m][n]/
GAMMA1 + dmag);
349 dtilde[m][n][0] += 2*dnew[n][0] - Cu[n][0] - d[m][n][0];
350 d[m][n][0] = dnew[n][0];
384 float UGaussSeidel(
float *Image,
float *b,
float (*dtilde)[NUMNEIGH][3],
385 const float *Mosaic,
int Width,
int Height,
int RedX,
int RedY)
387 const int NumPixels = Width*Height;
388 const int GreenPos = 1 - ((RedX + RedY) & 1);
390 float *Green = Image + NumPixels;
391 float *Blue = Image + 2*NumPixels;
392 float DiffNorm = 0, Rhs[3], Sum[3], NewRed, NewGreen, NewBlue;
393 int Channel, m, x, y, n, NumNeigh, nOffset[
NUMNEIGH];
396 nOffset[n] = NeighX[n] + Width*NeighY[n];
398 for(y = 0, m = 0; y < Height; y++)
400 for(x = 0; x < Width; x++, m++)
402 Rhs[0] = Rhs[1] = Rhs[2] = 0;
403 Sum[0] = Sum[1] = Sum[2] = 0;
408 if(0 < x && x < Width - 1 && 0 < y && y < Height - 1)
414 Rhs[0] += Red[m + nOffset[n]];
415 Rhs[1] += Green[m + nOffset[n]];
416 Rhs[2] += Blue[m + nOffset[n]];
418 for(Channel = 0; Channel < 3; Channel++)
419 Sum[Channel] += dtilde[m][n][Channel]
420 - dtilde[m + nOffset[n]][NeighAdj[n]][Channel];
424 for(n = 0, NumNeigh = 0; n <
NUMNEIGH; n++)
425 if(0 <= x + NeighX[n] && x + NeighX[n] < Width
426 && 0 <= y + NeighY[n] && y + NeighY[n] < Height)
429 Rhs[0] += Red[m + nOffset[n]];
430 Rhs[1] += Green[m + nOffset[n]];
431 Rhs[2] += Blue[m + nOffset[n]];
433 for(Channel = 0; Channel < 3; Channel++)
434 Sum[Channel] += dtilde[m][n][Channel]
435 - dtilde[m + nOffset[n]][NeighAdj[n]][Channel];
441 Sum[0] = (Sum[0]/2 + GetYComponent(Rhs[0], Rhs[1], Rhs[2]))
443 Sum[1] = (Sum[1]/2 + GetUComponent(Rhs[0], Rhs[1], Rhs[2]))
445 Sum[2] = (Sum[2]/2 + GetVComponent(Rhs[0], Rhs[1], Rhs[2]))
451 Rhs[0] = (float)(CMAT_YR*Sum[0] + CMAT_UR*Sum[1] + CMAT_VR*Sum[2]);
452 Rhs[1] = (float)(CMAT_YG*Sum[0] + CMAT_UG*Sum[1] + CMAT_VG*Sum[2]);
453 Rhs[2] = (float)(CMAT_YB*Sum[0] + CMAT_UB*Sum[1] + CMAT_VB*Sum[2]);
472 if(((x + y) & 1) == GreenPos)
474 Rhs[1] +=
MU*(Mosaic[m] - b[m]);
475 NewRed = UINVG_RR*Rhs[0] + UINVG_RG*Rhs[1] + UINVG_RB*Rhs[2];
476 NewGreen = UINVG_GR*Rhs[0] + UINVG_GG*Rhs[1] + UINVG_GB*Rhs[2];
477 NewBlue = UINVG_BR*Rhs[0] + UINVG_BG*Rhs[1] + UINVG_BB*Rhs[2];
478 b[m] += NewGreen - Mosaic[m];
480 else if((y & 1) == RedY)
482 Rhs[0] +=
MU*(Mosaic[m] - b[m]);
483 NewRed = UINVR_RR*Rhs[0] + UINVR_RG*Rhs[1] + UINVR_RB*Rhs[2];
484 NewGreen = UINVR_GR*Rhs[0] + UINVR_GG*Rhs[1] + UINVR_GB*Rhs[2];
485 NewBlue = UINVR_BR*Rhs[0] + UINVR_BG*Rhs[1] + UINVR_BB*Rhs[2];
486 b[m] += NewRed - Mosaic[m];
490 Rhs[2] +=
MU*(Mosaic[m] - b[m]);
491 NewRed = UINVB_RR*Rhs[0] + UINVB_RG*Rhs[1] + UINVB_RB*Rhs[2];
492 NewGreen = UINVB_GR*Rhs[0] + UINVB_GG*Rhs[1] + UINVB_GB*Rhs[2];
493 NewBlue = UINVB_BR*Rhs[0] + UINVB_BG*Rhs[1] + UINVB_BB*Rhs[2];
494 b[m] += NewBlue - Mosaic[m];
498 DiffNorm += sqr(NewRed - Red[m]);
499 DiffNorm += sqr(NewGreen - Green[m]);
500 DiffNorm += sqr(NewBlue - Blue[m]);
508 return (
float)sqrt(DiffNorm);
513 static int ConstantExtension(
int n,
int N)
515 return (n < 0) ? 0 : ((n >= N) ? (N-1) : n);
546 int Width,
int Height,
int RedX,
int RedY,
float Epsilon,
float Sigma)
548 const int NumPixels = Width*Height;
550 filter SmoothFilter = {NULL, 0, 0};
551 float *ConvTemp = NULL;
553 int i, j, n, x, y, Success = 0;
555 if(!(ConvTemp = (
float *)
Malloc(
sizeof(
float)*NumPixels))
556 || !(Stencil = (
int *)
Malloc(
sizeof(
int)*NumPixels))
565 for(y = 0, i = 0; y < Height; y++)
566 for(x = 0; x < Width; x++, i++)
568 Weight[i][n] = Epsilon + NeighWeights[Stencil[i]][n];
571 for(y = 0, i = 0; y < Height; y++)
572 for(x = 0; x < Width; x++, i++)
573 for(n = 0; n < 4; n++)
575 j = ConstantExtension(x + NeighX[n], Width)
576 + Width*ConstantExtension(y + NeighY[n], Height);
577 Weight[i][n] = (Weight[i][n] + Weight[j][NeighAdj[n]])/2;
580 for(y = 0, i = 0; y < Height; y++)
581 for(x = 0; x < Width; x++, i++)
584 j = ConstantExtension(x + NeighX[n], Width)
585 + Width*ConstantExtension(y + NeighY[n], Height);
586 Weight[i][n] = Weight[j][NeighAdj[n]];
592 for(y = 0; y < Height; y++)
593 Conv1D(ConvTemp + Width*y, 1,
594 (
float *)Weight + n + NUMNEIGH*Width*y, NUMNEIGH,
595 SmoothFilter, Boundary, Width);
597 for(x = 0; x < Width; x++)
598 Conv1D((
float *)Weight + n + NUMNEIGH*x, NUMNEIGH*Width,
600 SmoothFilter, Boundary, Height);
624 void CopyCfaValues(
float *Image,
const float *Mosaic,
int Width,
int Height,
627 const int NumPixels = Width*Height;
628 const int GreenPos = 1 - ((RedX + RedY) & 1);
630 float *Green = Image + NumPixels;
631 float *Blue = Image + 2*NumPixels;
634 for(y = 0, m = 0; y < Height; y++)
635 for(x = 0; x < Width; x++, m++)
636 if(((x + y) & 1) == GreenPos)
637 Green[m] = Mosaic[m];
638 else if((y & 1) == RedY)
671 int RedX,
int RedY,
float Alpha,
float (*Weight)[NUMNEIGH],
674 const int NumPixels = Width*Height;
675 float *Red = NULL, *Green, *Blue;
676 float Energy = 0, EnergyL, EnergyC, Diff[3], CDiff[3];
679 if(!(Red = (
float *)
Malloc(
sizeof(
float)*3*NumPixels)))
682 memcpy(Red, Image,
sizeof(
float)*3*NumPixels);
684 Green = Red + NumPixels;
685 Blue = Red + 2*NumPixels;
689 nOffset[n] = NeighX[n] + Width*NeighY[n];
691 for(y = 0, m = 0; y < Height; y++)
692 for(x = 0; x < Width; x++, m++)
694 EnergyL = EnergyC = 0;
697 if(0 <= x + NeighX[n] && x + NeighX[n] < Width
698 && 0 <= y + NeighY[n] && y + NeighY[n] < Height)
700 Diff[0] = Red[m] - Red[m + nOffset[n]];
701 Diff[1] = Green[m] - Green[m + nOffset[n]];
702 Diff[2] = Blue[m] - Blue[m + nOffset[n]];
705 CDiff[0] = GetYComponent(Diff[0], Diff[1], Diff[2]);
706 CDiff[1] = GetUComponent(Diff[0], Diff[1], Diff[2]);
707 CDiff[2] = GetVComponent(Diff[0], Diff[1], Diff[2]);
710 EnergyL += Weight[m][n]*CDiff[0]*CDiff[0];
712 EnergyC += Weight[m][n]*(
713 CDiff[1]*CDiff[1] + CDiff[2]*CDiff[2]);
716 Energy += (float)(sqrt(EnergyL) + Alpha*sqrt(EnergyC));
751 int RedX,
int RedY,
float Alpha,
float Epsilon,
float Sigma,
752 float Tol,
int MaxIter,
int ShowEnergy)
754 const int NumPixels = Width*Height;
755 const int NumEl = 3*NumPixels;
756 float *Mosaic = NULL, (*Weight)[
NUMNEIGH] = NULL, *b = NULL;
759 unsigned long StartTime;
762 int Iter, Channel, i, n, Success = 0;
765 if(!(Weight = (
float (*)[NUMNEIGH])
766 Malloc(
sizeof(
float)*NUMNEIGH*NumPixels))
767 || !(d = (
float (*)[NUMNEIGH][3])
768 Malloc(
sizeof(
float)*NUMNEIGH*NumEl))
769 || !(dtilde = (
float (*)[NUMNEIGH][3])
770 Malloc(
sizeof(
float)*NUMNEIGH*NumEl))
771 || !(b = (
float *)
Malloc(
sizeof(
float)*NumPixels))
772 || !(Mosaic = (
float *)
Malloc(
sizeof(
float)*NumPixels)))
779 CfaFlatten(Mosaic, Image, Width, Height, RedX, RedY);
783 RedX, RedY, Epsilon, Sigma))
787 for(i = 0, InputNorm = 0; i < NumPixels; i++)
788 InputNorm += Mosaic[i]*Mosaic[i];
790 Tol *= (float)sqrt(InputNorm);
798 for(i = 0; i < NumPixels; i++)
800 for(Channel = 0; Channel < 3; Channel++)
801 d[i][n][Channel] = 0;
803 for(i = 0; i < NumPixels; i++)
805 for(Channel = 0; Channel < 3; Channel++)
806 dtilde[i][n][Channel] = 0;
808 for(i = 0; i < NumPixels; i++)
819 printf(
" Iter Energy\n");
820 printf(
"%5d %10.1f\n", 0,
822 RedX, RedY, Alpha, Weight, Mosaic));
826 for(Iter = 1; Iter <= MaxIter; Iter++)
829 DShrink(d, dtilde, Image, Weight, Width, Height, Alpha);
832 Width, Height, RedX, RedY);
835 printf(
"%5d %10.1f\n", Iter,
837 RedX, RedY, Alpha, Weight, Mosaic));
839 if(DiffNorm <= Tol && Iter > 2)
841 printf(
"Converged in %d iterations.\n", Iter);
846 if(Iter > MaxIter && !(DiffNorm <= Tol))
847 printf(
"Maximum number of iterations exceeded.\n");
853 printf(
"CPU Time: %.3f s\n", 0.001f*(
Clock() - StartTime));