Skip to content

Commit d9ffc4c

Browse files
committed
photo: add support of all types of 1c images in inpaint
1 parent 2ddaaf6 commit d9ffc4c

File tree

3 files changed

+67
-31
lines changed

3 files changed

+67
-31
lines changed

modules/photo/include/opencv2/photo.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ enum
8989

9090
/** @brief Restores the selected region in an image using the region neighborhood.
9191
92-
@param src Input any 1-channel or 8-bit 3-channel image.
92+
@param src Input 8-bit, 16-bit unsigned or 32-bit float 1-channel or 8-bit 3-channel image.
9393
@param inpaintMask Inpainting mask, 8-bit 1-channel image. Non-zero pixels indicate the area that
9494
needs to be inpainted.
9595
@param dst Output image with the same size and type as src .

modules/photo/src/inpaint.cpp

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,6 @@ min4( float a, float b, float c, float d )
6767
#define INSIDE 2 //unknown
6868
#define CHANGE 3 //servise
6969

70-
// Processing data types
71-
typedef double data_type;
72-
int data_type_cv = CV_64F;
73-
7470
typedef struct CvHeapElem
7571
{
7672
float T;
@@ -281,7 +277,7 @@ icvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) {
281277
}
282278
}
283279

284-
280+
template <typename data_type>
285281
static void
286282
icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap ) {
287283
int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
@@ -513,7 +509,7 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu
513509
}
514510
}
515511

516-
512+
template <typename data_type>
517513
static void
518514
icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap) {
519515
int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
@@ -644,28 +640,28 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue
644640

645641
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
646642
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
647-
gradI.x=(float)(abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm))+
648-
abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)));
643+
gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm))+
644+
std::abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)));
649645
} else {
650-
gradI.x=(float)(abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm)))*2.0f;
646+
gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm)))*2.0f;
651647
}
652648
} else {
653649
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
654-
gradI.x=(float)(abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)))*2.0f;
650+
gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)))*2.0f;
655651
} else {
656652
gradI.x=0;
657653
}
658654
}
659655
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
660656
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
661-
gradI.y=(float)(abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm))+
662-
abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1)));
657+
gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm))+
658+
std::abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1)));
663659
} else {
664-
gradI.y=(float)(abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm)))*2.0f;
660+
gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm)))*2.0f;
665661
}
666662
} else {
667663
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
668-
gradI.y=(float)(abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1)))*2.0f;
664+
gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1)))*2.0f;
669665
} else {
670666
gradI.y=0;
671667
}
@@ -748,11 +744,13 @@ cvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_i
748744
if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask))
749745
CV_Error( CV_StsUnmatchedSizes, "All the input and output images must have the same size" );
750746

751-
if( (CV_MAT_CN(input_img->type) != 1 &&
747+
if( (CV_MAT_TYPE(input_img->type) != CV_8U &&
748+
CV_MAT_TYPE(input_img->type) != CV_16U &&
749+
CV_MAT_TYPE(input_img->type) != CV_32F &&
752750
CV_MAT_TYPE(input_img->type) != CV_8UC3) ||
753751
!CV_ARE_TYPES_EQ(input_img,output_img) )
754752
CV_Error( CV_StsUnsupportedFormat,
755-
"Any 1-channel and 8-bit 3-channel input/output images are supported" );
753+
"8-bit, 16-bit unsigned or 32-bit float 1-channel and 8-bit 3-channel input/output images are supported" );
756754

757755
if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 )
758756
CV_Error( CV_StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" );
@@ -802,10 +800,36 @@ cvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_i
802800
cvSub(out,band,out,NULL);
803801
SET_BORDER1_C1(out,uchar,0);
804802
icvCalcFMM(out,t,Out,true);
805-
icvTeleaInpaintFMM(mask,t,output_img,range,Heap);
803+
switch(CV_MAT_DEPTH(output_img->type))
804+
{
805+
case CV_8U:
806+
icvTeleaInpaintFMM<uchar>(mask,t,output_img,range,Heap);
807+
break;
808+
case CV_16U:
809+
icvTeleaInpaintFMM<ushort>(mask,t,output_img,range,Heap);
810+
break;
811+
case CV_32F:
812+
icvTeleaInpaintFMM<float>(mask,t,output_img,range,Heap);
813+
break;
814+
default:
815+
CV_Error( cv::Error::StsBadArg, "Unsupportedformat of the input image" );
816+
}
806817
}
807818
else if (flags == cv::INPAINT_NS) {
808-
icvNSInpaintFMM(mask,t,output_img,range,Heap);
819+
switch(CV_MAT_DEPTH(output_img->type))
820+
{
821+
case CV_8U:
822+
icvNSInpaintFMM<uchar>(mask,t,output_img,range,Heap);
823+
break;
824+
case CV_16U:
825+
icvNSInpaintFMM<ushort>(mask,t,output_img,range,Heap);
826+
break;
827+
case CV_32F:
828+
icvNSInpaintFMM<float>(mask,t,output_img,range,Heap);
829+
break;
830+
default:
831+
CV_Error( cv::Error::StsBadArg, "Unsupported format of the input image" );
832+
}
809833
} else {
810834
CV_Error( cv::Error::StsBadArg, "The flags argument must be one of CV_INPAINT_TELEA or CV_INPAINT_NS" );
811835
}
@@ -819,17 +843,6 @@ void cv::inpaint( InputArray _src, InputArray _mask, OutputArray _dst,
819843
Mat src = _src.getMat(), mask = _mask.getMat();
820844
_dst.create( src.size(), src.type() );
821845
Mat dst = _dst.getMat();
822-
823-
Mat src_temp;
824-
if (src.channels() == 1) {
825-
src.convertTo(src_temp, data_type_cv);
826-
} else
827-
src_temp = src.clone();
828-
829-
Mat dst_temp = Mat::zeros(src_temp.size(), src_temp.type());
830-
CvMat c_src = src_temp, c_mask = mask, c_dst = dst_temp;
846+
CvMat c_src = src, c_mask = mask, c_dst = dst;
831847
cvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags );
832-
833-
if (src.channels() == 1) dst_temp.convertTo(dst_temp, src.type());
834-
dst_temp.copyTo(dst);
835848
}

modules/photo/test/test_inpaint.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,26 @@ void CV_InpaintTest::run( int )
117117
}
118118

119119
TEST(Photo_Inpaint, regression) { CV_InpaintTest test; test.safe_run(); }
120+
121+
typedef testing::TestWithParam<std::tr1::tuple<int> > formats;
122+
123+
TEST_P(formats, 1c)
124+
{
125+
const int type = std::tr1::get<0>(GetParam());
126+
Mat src(100, 100, type);
127+
src.setTo(Scalar::all(128));
128+
Mat ref = src.clone();
129+
Mat dst, mask = Mat::zeros(src.size(), CV_8U);
130+
131+
circle(src, Point(50, 50), 5, Scalar(200), 6);
132+
circle(mask, Point(50, 50), 5, Scalar(200), 6);
133+
inpaint(src, mask, dst, 10, INPAINT_NS);
134+
135+
Mat dst2;
136+
inpaint(src, mask, dst2, 10, INPAINT_TELEA);
137+
138+
ASSERT_LE(cv::norm(dst, ref, NORM_INF), 3.);
139+
ASSERT_LE(cv::norm(dst2, ref, NORM_INF), 3.);
140+
}
141+
142+
INSTANTIATE_TEST_CASE_P(Photo_Inpaint, formats, testing::Values(CV_32F, CV_16U, CV_8U));

0 commit comments

Comments
 (0)