MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
ImageTransforms.cs
1using MyCaffe.basecode;
2using MyCaffe.common;
3using MyCaffe.param;
4using MyCaffe.param.ssd;
5using System;
6using System.Collections.Generic;
7using System.Drawing;
8using System.Linq;
9using System.Text;
10using System.Threading.Tasks;
11
12namespace MyCaffe.data
13{
22 public class ImageTransforms<T>
23 {
24 CryptoRandom m_random;
25 CudaDnn<T> m_cuda;
26 Log m_log;
27
34 public ImageTransforms(CudaDnn<T> cuda, Log log, CryptoRandom random)
35 {
36 m_random = random;
37 m_cuda = cuda;
38 m_log = log;
39 }
40
49 public NormalizedBBox UpdateBBoxByResizePolicy(ResizeParameter p, int nOldWidth, int nOldHeight, NormalizedBBox bbox1)
50 {
51 NormalizedBBox bbox = bbox1.Clone();
52 float fNewHeight = p.height;
53 float fNewWidth = p.width;
54 float fOrigAspect = (float)nOldWidth / (float)nOldHeight;
55 float fNewAspect = fNewWidth / fNewHeight;
56
57 float fxmin = bbox.xmin * nOldWidth;
58 float fymin = bbox.ymin * nOldHeight;
59 float fxmax = bbox.xmax * nOldWidth;
60 float fymax = bbox.ymax * nOldHeight;
61 float fPadding;
62
63 switch (p.resize_mode)
64 {
66 fxmin = (float)Math.Max(0.0, fxmin * fNewWidth / nOldWidth);
67 fxmax = (float)Math.Min(fNewWidth, fxmax * fNewWidth / nOldWidth);
68 fymin = (float)Math.Max(0.0, fymin * fNewHeight / nOldHeight);
69 fymax = (float)Math.Min(fNewHeight, fymax * fNewHeight / nOldHeight);
70 break;
71
72 case ResizeParameter.ResizeMode.FIT_LARGE_SIZE_AND_PAD:
73 if (fOrigAspect > fNewAspect)
74 {
75 fPadding = (fNewHeight - fNewWidth / fOrigAspect) / 2;
76 fxmin = (float)Math.Max(0.0, fxmin * fNewWidth / nOldWidth);
77 fxmax = (float)Math.Min(fNewWidth, fxmax * fNewWidth / nOldWidth);
78 fymin = fymin * (fNewHeight - 2 * fPadding) / nOldHeight;
79 fymin = fPadding + Math.Max(0, fymin);
80 fymax = fymax * (fNewHeight - 2 * fPadding) / nOldHeight;
81 fymax = fPadding + Math.Min(fNewHeight, fymax);
82 }
83 else
84 {
85 fPadding = (fNewWidth - fOrigAspect * fNewHeight) / 2;
86 fxmin = fxmin * (fNewWidth - 2 * fPadding) / nOldWidth;
87 fxmin = fPadding + Math.Max(0, fxmin);
88 fxmax = fxmax * (fNewWidth - 2 * fPadding) / nOldWidth;
89 fxmax = fPadding + Math.Min(fNewWidth, fxmax);
90 fymin = (float)Math.Max(0.0, fymin * fNewHeight / nOldHeight);
91 fymax = (float)Math.Min(fNewHeight, fymax * fNewHeight / nOldHeight);
92 }
93 break;
94
95 case ResizeParameter.ResizeMode.FIT_SMALL_SIZE:
96 if (fOrigAspect < fNewAspect)
97 fNewHeight = fNewWidth / fOrigAspect;
98 else
99 fNewWidth = fOrigAspect * fNewHeight;
100
101 fxmin = (float)Math.Max(0.0, fxmin * fNewWidth / nOldWidth);
102 fxmax = (float)Math.Min(fNewWidth, fxmax * fNewWidth / nOldWidth);
103 fymin = (float)Math.Max(0.0, fymin * fNewHeight / nOldHeight);
104 fymax = (float)Math.Min(fNewHeight, fymax * fNewHeight / nOldHeight);
105 break;
106
107 default:
108 m_log.FAIL("Unknown resize mode '" + p.resize_mode.ToString() + "'!");
109 break;
110 }
111
112 bbox.xmin = fxmin / fNewWidth;
113 bbox.ymin = fymin / fNewHeight;
114 bbox.xmax = fxmax / fNewWidth;
115 bbox.ymax = fymax / fNewHeight;
116
117 return bbox;
118 }
119
128 public void InferNewSize(ResizeParameter p, int nOldWidth, int nOldHeight, out int nNewWidth, out int nNewHeight)
129 {
130 int height = (int)p.height;
131 int width = (int)p.width;
132 float fOrigAspect = (float)nOldWidth / (float)nOldHeight;
133 float fAspect = (float)width / (float)height;
134
135 switch (p.resize_mode)
136 {
137 case ResizeParameter.ResizeMode.WARP:
138 break;
139
140 case ResizeParameter.ResizeMode.FIT_LARGE_SIZE_AND_PAD:
141 break;
142
143 case ResizeParameter.ResizeMode.FIT_SMALL_SIZE:
144 if (fOrigAspect < fAspect)
145 height = (int)(width / fOrigAspect);
146 else
147 width = (int)(fOrigAspect * height);
148 break;
149
150 default:
151 m_log.FAIL("Unknown resize mode '" + p.resize_mode.ToString() + "'!");
152 break;
153 }
154
155 nNewHeight = height;
156 nNewWidth = width;
157 }
158
159 private float getRandom(float fMin, float fMax, float fTotal = 256)
160 {
161 float fRange = fMax - fMin;
162 double dfVal = m_random.NextDouble();
163 double dfPct = ((fMin + (float)(fRange * dfVal)) / fTotal);
164
165 return 1.0f + (float)dfPct;
166 }
167
168 private Bitmap randomBrightness(Bitmap bmp, float fProb, float fDelta)
169 {
170 if (m_random.NextDouble() < fProb)
171 {
172 float fBrightness = getRandom(-fDelta, fDelta);
173 Bitmap bmpNew = ImageTools.AdjustContrast(bmp, fBrightness);
174 bmp.Dispose();
175 return bmpNew;
176 }
177
178 return bmp;
179 }
180
181 private Bitmap randomContrast(Bitmap bmp, float fProb, float fLower, float fUpper)
182 {
183 if (m_random.NextDouble() < fProb)
184 {
185 float fContrast = getRandom(fLower, fUpper);
186 Bitmap bmpNew = ImageTools.AdjustContrast(bmp, 1, fContrast);
187 bmp.Dispose();
188 return bmpNew;
189 }
190
191 return bmp;
192 }
193
194 private Bitmap randomSaturation(Bitmap bmp, float fProb, float fLower, float fUpper)
195 {
196 if (m_random.NextDouble() < fProb)
197 {
198 float fSaturation = getRandom(fLower, fUpper);
199 Bitmap bmpNew = ImageTools.AdjustContrast(bmp, 1, 1, fSaturation);
200 bmp.Dispose();
201 return bmpNew;
202 }
203
204 return bmp;
205 }
206
207 private Bitmap randomBrightnessContrastSaturation(Bitmap bmp, float fProbBrightness, float fBrightnessDelta, float fProbContrast, float fLowerContrast, float fUpperContrast, float fProbSaturation, float fLowerSaturation, float fUpperSaturation)
208 {
209 float fBrightness = 1;
210 float fContrast = 1;
211 float fSaturation = 1;
212
213 if (m_random.NextDouble() < fProbBrightness)
214 fBrightness = getRandom(-fBrightnessDelta, fBrightnessDelta);
215
216 if (m_random.NextDouble() < fProbContrast)
217 fContrast = getRandom(fLowerContrast, fUpperContrast);
218
219 if (m_random.NextDouble() < fProbSaturation)
220 fSaturation = getRandom(fLowerSaturation, fUpperSaturation);
221
222 if (fBrightness == 0 && fContrast == 1 && fSaturation == 1)
223 return bmp;
224
225 Bitmap bmpNew = ImageTools.AdjustContrast(bmp, fBrightness, fContrast, fSaturation);
226 bmp.Dispose();
227
228 return bmpNew;
229 }
230
231 private Bitmap randomBrightnessSaturationContrast(Bitmap bmp, float fProbBrightness, float fBrightnessDelta, float fProbContrast, float fLowerContrast, float fUpperContrast, float fProbSaturation, float fLowerSaturation, float fUpperSaturation)
232 {
233 float fBrightness = 1;
234 float fContrast = 1;
235 float fSaturation = 1;
236
237 if (m_random.NextDouble() < fProbBrightness)
238 fBrightness = getRandom(-fBrightnessDelta, fBrightnessDelta);
239
240 if (m_random.NextDouble() < fProbContrast)
241 fContrast = getRandom(fLowerContrast, fUpperContrast);
242
243 if (m_random.NextDouble() < fProbSaturation)
244 fSaturation = getRandom(fLowerSaturation, fUpperSaturation);
245
246 if (fBrightness == 0 && fContrast == 1 && fSaturation == 1)
247 return bmp;
248
249 Bitmap bmpNew = ImageTools.AdjustContrast(bmp, fBrightness, 1, fSaturation);
250 bmp.Dispose();
251 bmp = bmpNew;
252
253 if (fContrast != 1)
254 {
255 bmpNew = ImageTools.AdjustContrast(bmp, 1, fContrast, 1);
256 bmp.Dispose();
257 bmp = bmpNew;
258 }
259
260 return bmp;
261 }
262
263 private void randomBrightnessContrastSaturation(SimpleDatum sd, float fProbBrightness, float fBrightnessDelta, float fProbContrast, float fLowerContrast, float fUpperContrast, float fProbSaturation, float fLowerSaturation, float fUpperSaturation, ImageTools.ADJUSTCONTRAST_ORDERING ordering)
264 {
265 float fBrightness = 1;
266 float fContrast = 1;
267 float fSaturation = 1;
268
269 if (m_random.NextDouble() < fProbBrightness)
270 fBrightness = getRandom(-fBrightnessDelta, fBrightnessDelta);
271
272 if (m_random.NextDouble() < fProbContrast)
273 fContrast = getRandom(fLowerContrast, fUpperContrast);
274
275 if (m_random.NextDouble() < fProbSaturation)
276 fSaturation = getRandom(fLowerSaturation, fUpperSaturation);
277
278 if (fBrightness == 0 && fContrast == 1 && fSaturation == 1)
279 return;
280
281 ImageTools.AdjustContrast(sd, fBrightness, fContrast, fSaturation, ordering);
282 }
283
284 private SimpleDatum randomChannelOrder(SimpleDatum sd, float fProb)
285 {
286 if (m_random.NextDouble() < fProb)
287 {
288 if (sd.IsRealData)
289 {
290 if (sd.RealDataD != null)
291 {
292 int nOffset = 0;
293 int nCount = sd.ItemCount / sd.Channels;
294 List<double[]> rgrgData = new List<double[]>();
295 List<int> rgIdx = new List<int>();
296
297 for (int i = 0; i < sd.Channels; i++)
298 {
299 double[] rgData = new double[nCount];
300 Array.Copy(sd.RealDataD, nOffset, rgData, 0, nCount);
301 rgrgData.Add(rgData);
302 rgIdx.Add(i);
303 nOffset += nCount;
304 }
305
306 List<int> rgOrder = new List<int>();
307 while (rgOrder.Count < sd.Channels)
308 {
309 int nIdx = m_random.Next(sd.Channels);
310 if (!rgOrder.Contains(nIdx))
311 rgOrder.Add(nIdx);
312 }
313
314 nOffset = 0;
315 for (int i = 0; i < sd.Channels; i++)
316 {
317 int nIdx = rgOrder[i];
318 Array.Copy(rgrgData[nIdx], 0, sd.RealDataD, nOffset, nCount);
319 nOffset += nCount;
320 }
321 }
322 else if (sd.RealDataF != null)
323 {
324 int nOffset = 0;
325 int nCount = sd.ItemCount / sd.Channels;
326 List<float[]> rgrgData = new List<float[]>();
327 List<int> rgIdx = new List<int>();
328
329 for (int i = 0; i < sd.Channels; i++)
330 {
331 float[] rgData = new float[nCount];
332 Array.Copy(sd.RealDataF, nOffset, rgData, 0, nCount);
333 rgrgData.Add(rgData);
334 rgIdx.Add(i);
335 nOffset += nCount;
336 }
337
338 List<int> rgOrder = new List<int>();
339 while (rgOrder.Count < sd.Channels)
340 {
341 int nIdx = m_random.Next(sd.Channels);
342 if (!rgOrder.Contains(nIdx))
343 rgOrder.Add(nIdx);
344 }
345
346 nOffset = 0;
347 for (int i = 0; i < sd.Channels; i++)
348 {
349 int nIdx = rgOrder[i];
350 Array.Copy(rgrgData[nIdx], 0, sd.RealDataF, nOffset, nCount);
351 nOffset += nCount;
352 }
353 }
354 else
355 {
356 throw new Exception("SimpleDatum: Both the RealDataD and RealDataF are null!");
357 }
358 }
359 else
360 {
361 int nOffset = 0;
362 int nCount = sd.ItemCount / sd.Channels;
363 List<byte[]> rgrgData = new List<byte[]>();
364 List<int> rgIdx = new List<int>();
365
366 for (int i = 0; i < sd.Channels; i++)
367 {
368 byte[] rgData = new byte[nCount];
369 Array.Copy(sd.ByteData, nOffset, rgData, 0, nCount);
370 rgrgData.Add(rgData);
371 rgIdx.Add(i);
372 nOffset += nCount;
373 }
374
375 List<int> rgOrder = new List<int>();
376 while (rgOrder.Count < sd.Channels)
377 {
378 int nIdx = m_random.Next(sd.Channels);
379 if (!rgOrder.Contains(nIdx))
380 rgOrder.Add(nIdx);
381 }
382
383 nOffset = 0;
384 for (int i = 0; i < sd.Channels; i++)
385 {
386 int nIdx = rgOrder[i];
387 Array.Copy(rgrgData[nIdx], 0, sd.ByteData, nOffset, nCount);
388 nOffset += nCount;
389 }
390 }
391 }
392
393 return sd;
394 }
395
403 {
404 double dfProb = m_random.NextDouble();
405 Bitmap bmp = ImageData.GetImage(sd);
406
407 if (dfProb > 0.5)
408 bmp = randomBrightnessContrastSaturation(bmp, p.brightness_prob, p.brightness_delta, p.contrast_prob, p.contrast_lower, p.contrast_upper, p.saturation_prob, p.saturation_lower, p.saturation_upper);
409 else
410 bmp = randomBrightnessSaturationContrast(bmp, p.brightness_prob, p.brightness_delta, p.contrast_prob, p.contrast_lower, p.contrast_upper, p.saturation_prob, p.saturation_lower, p.saturation_upper);
411
412 SimpleDatum sd1 = ImageData.GetImageData(bmp, sd);
413 sd.SetData(sd1);
414
415 bmp.Dispose();
416
417 return randomChannelOrder(sd, p.random_order_prob);
418 }
419
427 {
428 double dfProb = m_random.NextDouble();
429
430 if (dfProb > 0.5)
431 randomBrightnessContrastSaturation(sd, p.brightness_prob, p.brightness_delta, p.contrast_prob, p.contrast_lower, p.contrast_upper, p.saturation_prob, p.saturation_lower, p.saturation_upper, ImageTools.ADJUSTCONTRAST_ORDERING.BRIGHTNESS_CONTRAST_GAMMA);
432 else
433 randomBrightnessContrastSaturation(sd, p.brightness_prob, p.brightness_delta, p.contrast_prob, p.contrast_lower, p.contrast_upper, p.saturation_prob, p.saturation_lower, p.saturation_upper, ImageTools.ADJUSTCONTRAST_ORDERING.BRIGHTNESS_GAMMA_CONTRAST);
434
435 return randomChannelOrder(sd, p.random_order_prob);
436 }
437
447 {
448 m_log.WriteLine("WARNING: noise application not yet implemented.");
449 return sd;
450 }
451
459 {
460 if (p.width == sd.Width && p.height == sd.Height)
461 return sd;
462
463 Bitmap bmp = ImageData.GetImage(sd);
464 Bitmap bmpNew = ImageTools.ResizeImage(bmp, (int)p.width, (int)p.height);
465 SimpleDatum sdResize = ImageData.GetImageData(bmpNew, sd, false);
466 SimpleDatum sdNew = new SimpleDatum(sd);
467
468 sdNew.CopyData(sdResize);
469
470 bmp.Dispose();
471 bmpNew.Dispose();
472
473 return sdNew;
474 }
475 }
476}
The CryptoRandom is a random number generator that can use either the standard .Net Random objec or t...
Definition: CryptoRandom.cs:14
The ImageData class is a helper class used to convert between Datum, other raw data,...
Definition: ImageData.cs:14
static Datum GetImageData(Bitmap bmp, SimpleDatum sd, bool? bIsDataRealOverride=null, int[] rgFocusMap=null)
The GetImageData function converts a Bitmap into a Datum.
Definition: ImageData.cs:23
static Bitmap GetImage(SimpleDatum d, ColorMapper clrMap=null, List< int > rgClrOrder=null)
Converts a SimplDatum (or Datum) into an image, optionally using a ColorMapper.
Definition: ImageData.cs:506
The ImageTools class is a helper class used to manipulate image data.
Definition: ImageTools.cs:16
ADJUSTCONTRAST_ORDERING
Defines the odering for which the AdjustContrast applies brightness, contrast and gamma adjustments.
Definition: ImageTools.cs:21
static Bitmap ResizeImage(Image image, int width, int height)
Resize the image to the specified width and height.
Definition: ImageTools.cs:39
static Bitmap AdjustContrast(Image bmp, float fBrightness=0.0f, float fContrast=1.0f, float fGamma=1.0f)
The AdjustContrast function adjusts the brightness, contrast and gamma of the image and returns the n...
Definition: ImageTools.cs:75
The Log class provides general output in text form.
Definition: Log.cs:13
void WriteLine(string str, bool bOverrideEnabled=false, bool bHeader=false, bool bError=false, bool bDisable=false)
Write a line of output.
Definition: Log.cs:80
void FAIL(string str)
Causes a failure which throws an exception with the desciptive text.
Definition: Log.cs:394
The NormalizedBBox manages a bounding box used in SSD.
float ymax
Get/set the y maximum.
float xmax
Get/set the x maximum.
NormalizedBBox Clone()
Return a copy of the object.
float xmin
Get/set the x minimum.
float ymin
Get/set the y minimum.
The SimpleDatum class holds a data input within host memory.
Definition: SimpleDatum.cs:161
void CopyData(SimpleDatum d)
Copy just the data from another SimpleDatum, making sure to update the C x H x W dimensions and IsRea...
int ItemCount
Returns the number of data items.
void SetData(SimpleDatum d)
Set the data of the current SimpleDatum by copying the data of another.
int Channels
Return the number of channels of the data.
bool IsRealData
Returns whether or not the data contains real numbers or byte data.
float[] RealDataF
Return the float data. This field is valid when IsRealData = true.
int Width
Return the width of the data.
byte[] ByteData
Return the byte data. This field is valid when IsRealData = false.
int Height
Return the height of the data.
double[] RealDataD
Return the double data. This field is valid when IsRealData = true.
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
The ImageTransforms class provides several useful image transformation function used with SSD.
void InferNewSize(ResizeParameter p, int nOldWidth, int nOldHeight, out int nNewWidth, out int nNewHeight)
Infer the new shape based on the resize policy.
SimpleDatum ApplyResize(SimpleDatum sd, ResizeParameter p)
The ApplyResize method resizes the SimpleDatum containing an image to a newly resized image as specif...
SimpleDatum ApplyDistortEx(SimpleDatum sd, DistortionParameter p)
The ApplyDistortEx method applies the distortion policy to the simple datum.
ImageTransforms(CudaDnn< T > cuda, Log log, CryptoRandom random)
The constructor.
SimpleDatum ApplyNoise(SimpleDatum sd, NoiseParameter p)
The ApplyNoise method applies the noise policy to the SimpleDatum.
NormalizedBBox UpdateBBoxByResizePolicy(ResizeParameter p, int nOldWidth, int nOldHeight, NormalizedBBox bbox1)
Update the BBox size based on the Resize policy.
SimpleDatum ApplyDistort(SimpleDatum sd, DistortionParameter p)
The ApplyDistort method applies the distortion policy to the simple datum.
Specifies the parameters for the DistortionParameter used with SSD.
float contrast_lower
Get/set lower bound for random contrast factor (default = 0.5).
float random_order_prob
Get/set the probability of randomly ordering the image channels (default = 0).
float brightness_delta
Get/set amount to add to the pixel values within [-delta,delta] (default = 0)
float saturation_prob
Get/set probability of adjusting the saturation (default = 0).
float saturation_lower
Get/set lower bound for random saturation factor (default = 0.5).
float saturation_upper
Get/set upper bound for random saturation factor (default = 1.5).
float brightness_prob
Get/set probability of adjusting the brightness (default = 0).
float contrast_prob
Get/set probability of adjusting the contrast (default = 0).
float contrast_upper
Get/set upper bound for random contrast factor (default = 1.5).
Specifies the parameters for the NoiseParameter used with SSD.
Specifies the parameters for the ResizeParameter for use with SSD.
uint height
Get/set the resizing height.
uint width
Get/set the resizing width.
ResizeMode
Defines the resizing mode.
ResizeMode resize_mode
Get/set the resizing mode.
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
The MyCaffe.common namespace contains common MyCaffe classes.
Definition: BatchInput.cs:8
The MyCaffe.data namespace contains dataset creators used to create common testing datasets such as M...
Definition: BinaryFile.cs:16
The MyCaffe.param.ssd namespace contains all SSD related parameter objects that correspond to the nat...
The MyCaffe.param namespace contains parameters used to create models.
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12