1 /***************************************************************************
2 
3         Blending remover
4 
5         A B C D E -> A AB B
6 
7     copyright            : (C) 2005 by mean
8     email                : fixounet@free.fr
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version.                                   *
17  *                                                                         *
18  ***************************************************************************/
19 #include "ADM_default.h"
20 #include "ADM_videoFilterDynamic.h"
21 #include <math.h>
22 #include "DIA_enter.h"
23 #include "DIA_factory.h"
24 #include "ADM_vidBlendRemoval_param.h"
25 #define MUL 1
26 // Set it to 2 for post separate field
27 
28 
29 
30 class vidBlendRemoval:public AVDMGenericVideoStream
31 {
32 
33 protected:
34   virtual char *printConf (void);
35   VideoCache *vidCache;
36   BLEND_REMOVER_PARAM *_param;
37   uint32_t              _lastRemoved;
38   ADMImage              *rebuild;
39 public:
40 
41                         vidBlendRemoval (AVDMGenericVideoStream * in, CONFcouple * setup);
42         virtual         ~vidBlendRemoval ();
43   virtual uint8_t getFrameNumberNoAlloc (uint32_t frame, uint32_t * len,
44                                          ADMImage * data, uint32_t * flags);
45   uint8_t configure (AVDMGenericVideoStream * instream);
46   virtual uint8_t getCoupledConf (CONFcouple ** couples);
47 
48 };
49 
50 static FILTER_PARAM field_unblend_template =
51   { 4,"threshold","show","noise","identical"};
52 
53 //*************************************
54 VF_DEFINE_FILTER(vidBlendRemoval,field_unblend_template,
55                 blendremoval,
56                 QT_TR_NOOP("Blend Removal"),
57                 1,
58                 VF_COLORS,
59                 QT_TR_NOOP("Try to remove blending."));
60 //*************************************
configure(AVDMGenericVideoStream * in)61 uint8_t vidBlendRemoval::configure (AVDMGenericVideoStream * in)
62 {
63 
64    _in=in;
65 
66 #define PX(x) &(_param->x)
67 
68     diaElemUInteger   thresh(PX(threshold),QT_TR_NOOP("_Threshold:"),0,99,
69         QT_TR_NOOP("If value is smaller than threshold it is considered valid."
70             "Smaller value might mean more false positive."));
71     diaElemUInteger   noise(PX(noise),QT_TR_NOOP("_Noise:"),0,99,QT_TR_NOOP("If pixels are closer than noise, they are considered to be the same"));
72     diaElemUInteger   identical(PX(identical),QT_TR_NOOP("I_dentical:"),0,99,QT_TR_NOOP("If metric is less than identical, images are considered identical"));
73     diaElemToggle     show(PX(show),QT_TR_NOOP("_Show metrics"),QT_TR_NOOP("Show metric in image (debug)"));
74 
75        diaElem *elems[]={&thresh,&noise,&identical,&show};
76 
77    if(  diaFactoryRun(QT_TR_NOOP("Blend Removal"),sizeof(elems)/sizeof(diaElem *),elems))
78    {
79         _lastRemoved=0xFFFFFFF;
80         return 1;
81     }
82         return 0;
83 }
84 /*************************************/
printConf(void)85 char *vidBlendRemoval::printConf (void)
86 {
87   ADM_FILTER_DECLARE_CONF( " Blend Removal Thresh:%d Noise:%d Ident:%d",_param->threshold,_param->noise,_param->identical);
88 
89 }
90 
91 #define MAX_BLOCKS 50
92 /*************************************/
vidBlendRemoval(AVDMGenericVideoStream * in,CONFcouple * couples)93 vidBlendRemoval::vidBlendRemoval (AVDMGenericVideoStream * in, CONFcouple * couples)
94 {
95 
96   _in = in;
97   memcpy (&_info, _in->getInfo (), sizeof (_info));
98   _info.encoding = 1;
99   vidCache = new VideoCache (10, in);
100   _uncompressed=new ADMImage(_info.width,_info.height);
101   rebuild=new ADMImage(_info.width,_info.height);
102 
103  _param=new BLEND_REMOVER_PARAM;
104  _lastRemoved=0xFFFF;
105  if(couples)
106  {
107 #undef GET
108 #define GET(x) couples->getCouple(#x,&(_param->x))
109       GET (threshold);
110       GET (show);
111       GET (noise);
112       GET (identical);
113   }
114   else
115   {
116         _param->threshold=10;
117         _param->show=0;
118         _param->noise=5;
119         _param->identical=2;
120   }
121 }
122 //____________________________________________________________________
~vidBlendRemoval()123 vidBlendRemoval::~vidBlendRemoval ()
124 {
125 
126   delete vidCache;
127   vidCache = NULL;
128   delete _uncompressed;
129   _uncompressed=NULL;
130   delete _param;
131   _param=NULL;
132   delete rebuild;
133   rebuild=NULL;
134 }
135 
136 
137 
138 
139 
getFrameNumberNoAlloc(uint32_t inframe,uint32_t * len,ADMImage * data,uint32_t * flags)140 uint8_t vidBlendRemoval::getFrameNumberNoAlloc (uint32_t inframe,
141                                 uint32_t * len,
142                                 ADMImage * data, uint32_t * flags)
143 {
144 
145 
146 	ADMImage *srcP,*srcN,*src,*final,*display;
147         float distMerged, distN,distP,distM,distR,skip=0;
148         char txt[255];
149 
150         if(inframe>= _info.nb_frames) return 0;
151         if(inframe<1 || inframe>inframe>_info.nb_frames-2 )
152         {
153                 skip=1;
154         }
155         if(inframe && _lastRemoved==inframe-1)
156         {
157                 skip=1;
158         }
159 
160         if(skip)
161         {
162                 data->duplicate(vidCache->getImage(inframe));
163                 vidCache->unlockAll();
164                 return 1;
165         }
166 
167 
168 
169         srcP=vidCache->getImage(inframe-1);
170         src=vidCache->getImage(inframe);
171         srcN=vidCache->getImage(inframe+1);
172         if(!srcP || !src || !srcN)
173         {
174                 data->duplicate(vidCache->getImage(inframe));
175                 vidCache->unlockAll();
176                 return 1;
177         }
178 
179         rebuild->merge(srcP,srcN);
180 
181         distP=ADMImage::lumaDiff(src,srcN,_param->noise);
182         distN=ADMImage::lumaDiff(src,srcP,_param->noise);
183         distM=ADMImage::lumaDiff(src,rebuild,_param->noise);
184 
185 
186 
187 
188         double medium;
189 
190          if(distN>1&&distP>1)
191         {
192                 if(distP>distN) medium=distN;
193                           else  medium=distP;
194                   //medium=min(distM,distR);
195 
196                  medium/=100;
197                  distN/=medium;
198                  distP/=medium;
199                  distM/=medium;
200 
201          }
202 
203         medium=medium/(_info.width*_info.height);
204         medium*=1000;
205         if(distM<_param->threshold && medium>_param->identical) // medium is how close pictures are, too close, we discard
206         {
207                 data->duplicate(srcP);
208                 _lastRemoved=inframe;
209                 if(_param->show )
210                 {
211                         sprintf(txt,"Dupe");
212                         drawString(data,2,5,txt);
213                 }
214         }
215         else
216                 data->duplicate(src);
217         if(_param->show)
218         {
219                 display=data;
220 
221                 sprintf(txt," N %02.1f",distN);
222                 drawString(display,2,0,txt);
223 
224                 sprintf(txt," P %02.1f",distP);
225                 drawString(display,2,1,txt);
226 
227                 sprintf(txt," M %02.1f",distM);
228                 drawString(display,2,2,txt);
229 
230                 sprintf(txt," %% %02.1f",medium);
231                 drawString(display,2,3,txt);
232         }
233 
234 
235 
236         vidCache->unlockAll();
237 	return 1;
238 }
getCoupledConf(CONFcouple ** couples)239 uint8_t vidBlendRemoval::getCoupledConf (CONFcouple ** couples)
240 {
241 
242   ADM_assert (_param);
243   *couples = new CONFcouple (4);
244 #undef CSET
245 #define CSET(x)  (*couples)->setCouple(#x,(_param->x))
246   CSET (threshold);
247   CSET (show);
248   CSET (noise);
249   CSET (identical);
250 
251   return 1;
252 }
253 
254 
255 //EOF
256