该算法使用区域邻域恢复图像中的选定区域。该功能可用于去除扫描照片上的灰尘和划痕,或去除静止图像或视频中不需要的物体。
void cv::inpaint (InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags)
| src | 输入 8 位、16 位无符号或 32 位浮点 1 通道或 8 位 3 通道图像。 |
| inpaintMask | 修复蒙版,8 位 1 通道图像。 非零像素表示需要修复的区域。 |
| dst | 输出与 src 大小和类型相同的图像 |
| inpaintRadius | 算法考虑的每个修复点的圆形邻域的半径。 |
| flags | 可以是 cv::INPAINT_NS 或 cv::INPAINT_TELEA 的修复方法 |
opencv\modules\photo\src\inpaint.cpp
- static void
- icvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_img,
- double inpaintRange, int flags )
- {
- cv::Ptr<CvMat> mask, band, f, t, out;
- cv::Ptr<CvPriorityQueueFloat> Heap, Out;
- cv::Ptr<IplConvKernel> el_cross, el_range;
-
- CvMat input_hdr, mask_hdr, output_hdr;
- CvMat* input_img, *inpaint_mask, *output_img;
- int range=cvRound(inpaintRange);
- int erows, ecols;
-
- input_img = cvGetMat( _input_img, &input_hdr );
- inpaint_mask = cvGetMat( _inpaint_mask, &mask_hdr );
- output_img = cvGetMat( _output_img, &output_hdr );
-
- if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask))
- CV_Error( CV_StsUnmatchedSizes, "All the input and output images must have the same size" );
-
- if( (CV_MAT_TYPE(input_img->type) != CV_8U &&
- CV_MAT_TYPE(input_img->type) != CV_16U &&
- CV_MAT_TYPE(input_img->type) != CV_32F &&
- CV_MAT_TYPE(input_img->type) != CV_8UC3) ||
- !CV_ARE_TYPES_EQ(input_img,output_img) )
- CV_Error( CV_StsUnsupportedFormat,
- "8-bit, 16-bit unsigned or 32-bit float 1-channel and 8-bit 3-channel input/output images are supported" );
-
- if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 )
- CV_Error( CV_StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" );
-
- range = MAX(range,1);
- range = MIN(range,100);
-
- ecols = input_img->cols + 2;
- erows = input_img->rows + 2;
-
- f.reset(cvCreateMat(erows, ecols, CV_8UC1));
- t.reset(cvCreateMat(erows, ecols, CV_32FC1));
- band.reset(cvCreateMat(erows, ecols, CV_8UC1));
- mask.reset(cvCreateMat(erows, ecols, CV_8UC1));
- el_cross.reset(cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL));
-
- cvCopy( input_img, output_img );
- cvSet(mask,cvScalar(KNOWN,0,0,0));
- COPY_MASK_BORDER1_C1(inpaint_mask,mask,uchar);
- SET_BORDER1_C1(mask,uchar,0);
- cvSet(f,cvScalar(KNOWN,0,0,0));
- cvSet(t,cvScalar(1.0e6f,0,0,0));
- cvDilate(mask,band,el_cross,1); // image with narrow band
- Heap=cv::makePtr<CvPriorityQueueFloat>();
- if (!Heap->Init(band))
- return;
- cvSub(band,mask,band,NULL);
- SET_BORDER1_C1(band,uchar,0);
- if (!Heap->Add(band))
- return;
- cvSet(f,cvScalar(BAND,0,0,0),band);
- cvSet(f,cvScalar(INSIDE,0,0,0),mask);
- cvSet(t,cvScalar(0,0,0,0),band);
-
- if( flags == cv::INPAINT_TELEA )
- {
- out.reset(cvCreateMat(erows, ecols, CV_8UC1));
- el_range.reset(cvCreateStructuringElementEx(2*range+1,2*range+1,
- range,range,CV_SHAPE_RECT,NULL));
- cvDilate(mask,out,el_range,1);
- cvSub(out,mask,out,NULL);
- Out=cv::makePtr<CvPriorityQueueFloat>();
- if (!Out->Init(out))
- return;
- if (!Out->Add(band))
- return;
- cvSub(out,band,out,NULL);
- SET_BORDER1_C1(out,uchar,0);
- icvCalcFMM(out,t,Out,true);
- switch(CV_MAT_DEPTH(output_img->type))
- {
- case CV_8U:
- icvTeleaInpaintFMM<uchar>(mask,t,output_img,range,Heap);
- break;
- case CV_16U:
- icvTeleaInpaintFMM<ushort>(mask,t,output_img,range,Heap);
- break;
- case CV_32F:
- icvTeleaInpaintFMM<float>(mask,t,output_img,range,Heap);
- break;
- default:
- CV_Error( cv::Error::StsBadArg, "Unsupportedformat of the input image" );
- }
- }
- else if (flags == cv::INPAINT_NS) {
- switch(CV_MAT_DEPTH(output_img->type))
- {
- case CV_8U:
- icvNSInpaintFMM<uchar>(mask,t,output_img,range,Heap);
- break;
- case CV_16U:
- icvNSInpaintFMM<ushort>(mask,t,output_img,range,Heap);
- break;
- case CV_32F:
- icvNSInpaintFMM<float>(mask,t,output_img,range,Heap);
- break;
- default:
- CV_Error( cv::Error::StsBadArg, "Unsupported format of the input image" );
- }
- } else {
- CV_Error( cv::Error::StsBadArg, "The flags argument must be one of CV_INPAINT_TELEA or CV_INPAINT_NS" );
- }
- }
-
- void cv::inpaint( InputArray _src, InputArray _mask, OutputArray _dst,
- double inpaintRange, int flags )
- {
- CV_INSTRUMENT_REGION();
-
- Mat src = _src.getMat(), mask = _mask.getMat();
- _dst.create( src.size(), src.type() );
- Mat dst = _dst.getMat();
- CvMat c_src = cvMat(src), c_mask = cvMat(mask), c_dst = cvMat(dst);
- icvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags );
- }