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