@@ -102,6 +102,38 @@ static IppStatus sts = ippInit();
102
102
103
103
namespace cv
104
104
{
105
+ // constants for conversion from/to RGB and Gray, YUV, YCrCb according to BT.601
106
+ const float B2YF = 0 .114f ;
107
+ const float G2YF = 0 .587f ;
108
+ const float R2YF = 0 .299f ;
109
+ // to YCbCr
110
+ const float YCBF = 0 .564f ; // == 1/2/(1-B2YF)
111
+ const float YCRF = 0 .713f ; // == 1/2/(1-R2YF)
112
+ const int YCBI = 9241 ; // == YCBF*16384
113
+ const int YCRI = 11682 ; // == YCRF*16384
114
+ // to YUV
115
+ const float B2UF = 0 .492f ;
116
+ const float R2VF = 0 .877f ;
117
+ const int B2UI = 8061 ; // == B2UF*16384
118
+ const int R2VI = 14369 ; // == R2VF*16384
119
+ // from YUV
120
+ const float U2BF = 2 .032f ;
121
+ const float U2GF = -0 .395f ;
122
+ const float V2GF = -0 .581f ;
123
+ const float V2RF = 1 .140f ;
124
+ const int U2BI = 33292 ;
125
+ const int U2GI = -6472 ;
126
+ const int V2GI = -9519 ;
127
+ const int V2RI = 18678 ;
128
+ // from YCrCb
129
+ const float CR2RF = 1 .403f ;
130
+ const float CB2GF = -0 .344f ;
131
+ const float CR2GF = -0 .714f ;
132
+ const float CB2BF = 1 .773f ;
133
+ const int CR2RI = 22987 ;
134
+ const int CB2GI = -5636 ;
135
+ const int CR2GI = -11698 ;
136
+ const int CB2BI = 29049 ;
105
137
106
138
// computes cubic spline coefficients for a function: (xi=i, yi=f[i]), i=0..n
107
139
template <typename _Tp> static void splineBuild (const _Tp* f, int n, _Tp* tab)
@@ -402,9 +434,9 @@ struct IPPColor2GrayFunctor
402
434
{
403
435
IPPColor2GrayFunctor (ippiColor2GrayFunc _func) : func(_func)
404
436
{
405
- coeffs[0 ] = 0 . 114f ;
406
- coeffs[1 ] = 0 . 587f ;
407
- coeffs[2 ] = 0 . 299f ;
437
+ coeffs[0 ] = B2YF ;
438
+ coeffs[1 ] = G2YF ;
439
+ coeffs[2 ] = R2YF ;
408
440
}
409
441
bool operator ()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
410
442
{
668
700
{
669
701
yuv_shift = 14 ,
670
702
xyz_shift = 12 ,
671
- R2Y = 4899 ,
672
- G2Y = 9617 ,
673
- B2Y = 1868 ,
703
+ R2Y = 4899 , // B2YF*16384
704
+ G2Y = 9617 , // G2YF*16384
705
+ B2Y = 1868 , // B2YF*16384
674
706
BLOCK_SIZE = 256
675
707
};
676
708
@@ -709,7 +741,7 @@ template<typename _Tp> struct RGB2Gray
709
741
710
742
RGB2Gray (int _srccn, int blueIdx, const float * _coeffs) : srccn(_srccn)
711
743
{
712
- static const float coeffs0[] = { 0 . 299f , 0 . 587f , 0 . 114f };
744
+ static const float coeffs0[] = { R2YF, G2YF, B2YF };
713
745
memcpy ( coeffs, _coeffs ? _coeffs : coeffs0, 3 *sizeof (coeffs[0 ]) );
714
746
if (blueIdx == 0 )
715
747
std::swap (coeffs[0 ], coeffs[2 ]);
@@ -787,16 +819,18 @@ template<typename _Tp> struct RGB2YCrCb_f
787
819
{
788
820
typedef _Tp channel_type;
789
821
790
- RGB2YCrCb_f (int _srccn, int _blueIdx, const float * _coeffs ) : srccn(_srccn), blueIdx(_blueIdx)
822
+ RGB2YCrCb_f (int _srccn, int _blueIdx, bool _isCrCb ) : srccn(_srccn), blueIdx(_blueIdx), isCrCb(_isCrCb )
791
823
{
792
- static const float coeffs0[] = {0 .299f , 0 .587f , 0 .114f , 0 .713f , 0 .564f };
793
- memcpy (coeffs, _coeffs ? _coeffs : coeffs0, 5 *sizeof (coeffs[0 ]));
824
+ static const float coeffs_crb[] = { R2YF, G2YF, B2YF, YCRF, YCBF };
825
+ static const float coeffs_yuv[] = { R2YF, G2YF, B2YF, R2VF, B2UF };
826
+ memcpy (coeffs, isCrCb ? coeffs_crb : coeffs_yuv, 5 *sizeof (coeffs[0 ]));
794
827
if (blueIdx==0 ) std::swap (coeffs[0 ], coeffs[2 ]);
795
828
}
796
829
797
830
void operator ()(const _Tp* src, _Tp* dst, int n) const
798
831
{
799
832
int scn = srccn, bidx = blueIdx;
833
+ int yuvOrder = !isCrCb; // 1 if YUV, 0 if YCrCb
800
834
const _Tp delta = ColorChannel<_Tp>::half ();
801
835
float C0 = coeffs[0 ], C1 = coeffs[1 ], C2 = coeffs[2 ], C3 = coeffs[3 ], C4 = coeffs[4 ];
802
836
n *= 3 ;
@@ -805,10 +839,11 @@ template<typename _Tp> struct RGB2YCrCb_f
805
839
_Tp Y = saturate_cast<_Tp>(src[0 ]*C0 + src[1 ]*C1 + src[2 ]*C2);
806
840
_Tp Cr = saturate_cast<_Tp>((src[bidx^2 ] - Y)*C3 + delta);
807
841
_Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta);
808
- dst[i] = Y; dst[i+1 ] = Cr; dst[i+2 ] = Cb;
842
+ dst[i] = Y; dst[i+1 +yuvOrder ] = Cr; dst[i+2 -yuvOrder ] = Cb;
809
843
}
810
844
}
811
845
int srccn, blueIdx;
846
+ bool isCrCb;
812
847
float coeffs[5 ];
813
848
};
814
849
@@ -817,16 +852,18 @@ template<typename _Tp> struct RGB2YCrCb_i
817
852
{
818
853
typedef _Tp channel_type;
819
854
820
- RGB2YCrCb_i (int _srccn, int _blueIdx, const int * _coeffs )
821
- : srccn(_srccn), blueIdx(_blueIdx)
855
+ RGB2YCrCb_i (int _srccn, int _blueIdx, bool _isCrCb )
856
+ : srccn(_srccn), blueIdx(_blueIdx), isCrCb(_isCrCb)
822
857
{
823
- static const int coeffs0[] = {R2Y, G2Y, B2Y, 11682 , 9241 };
824
- memcpy (coeffs, _coeffs ? _coeffs : coeffs0, 5 *sizeof (coeffs[0 ]));
858
+ static const int coeffs_crb[] = { R2Y, G2Y, B2Y, YCRI, YCBI };
859
+ static const int coeffs_yuv[] = { R2Y, G2Y, B2Y, R2VI, B2UI };
860
+ memcpy (coeffs, isCrCb ? coeffs_crb : coeffs_yuv, 5 *sizeof (coeffs[0 ]));
825
861
if (blueIdx==0 ) std::swap (coeffs[0 ], coeffs[2 ]);
826
862
}
827
863
void operator ()(const _Tp* src, _Tp* dst, int n) const
828
864
{
829
865
int scn = srccn, bidx = blueIdx;
866
+ int yuvOrder = !isCrCb; // 1 if YUV, 0 if YCrCb
830
867
int C0 = coeffs[0 ], C1 = coeffs[1 ], C2 = coeffs[2 ], C3 = coeffs[3 ], C4 = coeffs[4 ];
831
868
int delta = ColorChannel<_Tp>::half ()*(1 << yuv_shift);
832
869
n *= 3 ;
@@ -836,11 +873,12 @@ template<typename _Tp> struct RGB2YCrCb_i
836
873
int Cr = CV_DESCALE ((src[bidx^2 ] - Y)*C3 + delta, yuv_shift);
837
874
int Cb = CV_DESCALE ((src[bidx] - Y)*C4 + delta, yuv_shift);
838
875
dst[i] = saturate_cast<_Tp>(Y);
839
- dst[i+1 ] = saturate_cast<_Tp>(Cr);
840
- dst[i+2 ] = saturate_cast<_Tp>(Cb);
876
+ dst[i+1 +yuvOrder ] = saturate_cast<_Tp>(Cr);
877
+ dst[i+2 -yuvOrder ] = saturate_cast<_Tp>(Cb);
841
878
}
842
879
}
843
880
int srccn, blueIdx;
881
+ bool isCrCb;
844
882
int coeffs[5 ];
845
883
};
846
884
@@ -849,23 +887,25 @@ template<typename _Tp> struct YCrCb2RGB_f
849
887
{
850
888
typedef _Tp channel_type;
851
889
852
- YCrCb2RGB_f (int _dstcn, int _blueIdx, const float * _coeffs )
853
- : dstcn(_dstcn), blueIdx(_blueIdx)
890
+ YCrCb2RGB_f (int _dstcn, int _blueIdx, bool _isCrCb )
891
+ : dstcn(_dstcn), blueIdx(_blueIdx), isCrCb(_isCrCb)
854
892
{
855
- static const float coeffs0[] = {1 .403f , -0 .714f , -0 .344f , 1 .773f };
856
- memcpy (coeffs, _coeffs ? _coeffs : coeffs0, 4 *sizeof (coeffs[0 ]));
893
+ static const float coeffs_cbr[] = {CR2RF, CR2GF, CB2GF, CB2BF};
894
+ static const float coeffs_yuv[] = { V2RF, V2GF, U2GF, U2BF};
895
+ memcpy (coeffs, isCrCb ? coeffs_cbr : coeffs_yuv, 4 *sizeof (coeffs[0 ]));
857
896
}
858
897
void operator ()(const _Tp* src, _Tp* dst, int n) const
859
898
{
860
899
int dcn = dstcn, bidx = blueIdx;
900
+ int yuvOrder = !isCrCb; // 1 if YUV, 0 if YCrCb
861
901
const _Tp delta = ColorChannel<_Tp>::half (), alpha = ColorChannel<_Tp>::max ();
862
902
float C0 = coeffs[0 ], C1 = coeffs[1 ], C2 = coeffs[2 ], C3 = coeffs[3 ];
863
903
n *= 3 ;
864
904
for (int i = 0 ; i < n; i += 3 , dst += dcn)
865
905
{
866
906
_Tp Y = src[i];
867
- _Tp Cr = src[i+1 ];
868
- _Tp Cb = src[i+2 ];
907
+ _Tp Cr = src[i+1 +yuvOrder ];
908
+ _Tp Cb = src[i+2 -yuvOrder ];
869
909
870
910
_Tp b = saturate_cast<_Tp>(Y + (Cb - delta)*C3);
871
911
_Tp g = saturate_cast<_Tp>(Y + (Cb - delta)*C2 + (Cr - delta)*C1);
@@ -877,6 +917,7 @@ template<typename _Tp> struct YCrCb2RGB_f
877
917
}
878
918
}
879
919
int dstcn, blueIdx;
920
+ bool isCrCb;
880
921
float coeffs[4 ];
881
922
};
882
923
@@ -885,24 +926,26 @@ template<typename _Tp> struct YCrCb2RGB_i
885
926
{
886
927
typedef _Tp channel_type;
887
928
888
- YCrCb2RGB_i (int _dstcn, int _blueIdx, const int * _coeffs )
889
- : dstcn(_dstcn), blueIdx(_blueIdx)
929
+ YCrCb2RGB_i (int _dstcn, int _blueIdx, bool _isCrCb )
930
+ : dstcn(_dstcn), blueIdx(_blueIdx), isCrCb(_isCrCb)
890
931
{
891
- static const int coeffs0[] = {22987 , -11698 , -5636 , 29049 };
892
- memcpy (coeffs, _coeffs ? _coeffs : coeffs0, 4 *sizeof (coeffs[0 ]));
932
+ static const int coeffs_crb[] = { CR2RI, CR2GI, CB2GI, CB2BI};
933
+ static const int coeffs_yuv[] = { V2RI, V2GI, U2GI, U2BI };
934
+ memcpy (coeffs, isCrCb ? coeffs_crb : coeffs_yuv, 4 *sizeof (coeffs[0 ]));
893
935
}
894
936
895
937
void operator ()(const _Tp* src, _Tp* dst, int n) const
896
938
{
897
939
int dcn = dstcn, bidx = blueIdx;
940
+ int yuvOrder = !isCrCb; // 1 if YUV, 0 if YCrCb
898
941
const _Tp delta = ColorChannel<_Tp>::half (), alpha = ColorChannel<_Tp>::max ();
899
942
int C0 = coeffs[0 ], C1 = coeffs[1 ], C2 = coeffs[2 ], C3 = coeffs[3 ];
900
943
n *= 3 ;
901
944
for (int i = 0 ; i < n; i += 3 , dst += dcn)
902
945
{
903
946
_Tp Y = src[i];
904
- _Tp Cr = src[i+1 ];
905
- _Tp Cb = src[i+2 ];
947
+ _Tp Cr = src[i+1 +yuvOrder ];
948
+ _Tp Cb = src[i+2 -yuvOrder ];
906
949
907
950
int b = Y + CV_DESCALE ((Cb - delta)*C3, yuv_shift);
908
951
int g = Y + CV_DESCALE ((Cb - delta)*C2 + (Cr - delta)*C1, yuv_shift);
@@ -916,6 +959,7 @@ template<typename _Tp> struct YCrCb2RGB_i
916
959
}
917
960
}
918
961
int dstcn, blueIdx;
962
+ bool isCrCb;
919
963
int coeffs[4 ];
920
964
};
921
965
@@ -3832,10 +3876,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3832
3876
{
3833
3877
CV_Assert ( scn == 3 || scn == 4 );
3834
3878
bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2 ;
3835
- static const float yuv_f[] = { 0 .114f , 0 .587f , 0 .299f , 0 .492f , 0 .877f };
3836
- static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061 , 14369 };
3837
- const float * coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;
3838
- const int * coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;
3879
+ const bool isCrCb = (code == CV_BGR2YCrCb || code == CV_RGB2YCrCb);
3839
3880
3840
3881
_dst.create (sz, CV_MAKETYPE (depth, 3 ));
3841
3882
dst = _dst.getMat ();
@@ -3846,12 +3887,12 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3846
3887
if ((code == CV_RGB2YCrCb || code == CV_BGR2YCrCb) && tegra::cvtRGB2YCrCb (src, dst, bidx))
3847
3888
break ;
3848
3889
#endif
3849
- CvtColorLoop (src, dst, RGB2YCrCb_i<uchar>(scn, bidx, coeffs_i ));
3890
+ CvtColorLoop (src, dst, RGB2YCrCb_i<uchar>(scn, bidx, isCrCb ));
3850
3891
}
3851
3892
else if ( depth == CV_16U )
3852
- CvtColorLoop (src, dst, RGB2YCrCb_i<ushort>(scn, bidx, coeffs_i ));
3893
+ CvtColorLoop (src, dst, RGB2YCrCb_i<ushort>(scn, bidx, isCrCb ));
3853
3894
else
3854
- CvtColorLoop (src, dst, RGB2YCrCb_f<float >(scn, bidx, coeffs_f ));
3895
+ CvtColorLoop (src, dst, RGB2YCrCb_f<float >(scn, bidx, isCrCb ));
3855
3896
}
3856
3897
break ;
3857
3898
@@ -3861,20 +3902,17 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3861
3902
if ( dcn <= 0 ) dcn = 3 ;
3862
3903
CV_Assert ( scn == 3 && (dcn == 3 || dcn == 4 ) );
3863
3904
bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2 ;
3864
- static const float yuv_f[] = { 2 .032f , -0 .395f , -0 .581f , 1 .140f };
3865
- static const int yuv_i[] = { 33292 , -6472 , -9519 , 18678 };
3866
- const float * coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;
3867
- const int * coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;
3905
+ const bool isCrCb = (code == CV_YCrCb2BGR || code == CV_YCrCb2RGB);
3868
3906
3869
3907
_dst.create (sz, CV_MAKETYPE (depth, dcn));
3870
3908
dst = _dst.getMat ();
3871
3909
3872
3910
if ( depth == CV_8U )
3873
- CvtColorLoop (src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, coeffs_i ));
3911
+ CvtColorLoop (src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, isCrCb ));
3874
3912
else if ( depth == CV_16U )
3875
- CvtColorLoop (src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, coeffs_i ));
3913
+ CvtColorLoop (src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, isCrCb ));
3876
3914
else
3877
- CvtColorLoop (src, dst, YCrCb2RGB_f<float >(dcn, bidx, coeffs_f ));
3915
+ CvtColorLoop (src, dst, YCrCb2RGB_f<float >(dcn, bidx, isCrCb ));
3878
3916
}
3879
3917
break ;
3880
3918
0 commit comments