ncnn

Форк
0
/
crop.cpp 
652 строки · 18.9 Кб
1
// Tencent is pleased to support the open source community by making ncnn available.
2
//
3
// Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
4
//
5
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
6
// in compliance with the License. You may obtain a copy of the License at
7
//
8
// https://opensource.org/licenses/BSD-3-Clause
9
//
10
// Unless required by applicable law or agreed to in writing, software distributed
11
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
13
// specific language governing permissions and limitations under the License.
14

15
#include "crop.h"
16

17
namespace ncnn {
18

19
Crop::Crop()
20
{
21
    one_blob_only = true;
22
    support_inplace = false;
23
}
24

25
int Crop::load_param(const ParamDict& pd)
26
{
27
    woffset = pd.get(0, 0);
28
    hoffset = pd.get(1, 0);
29
    doffset = pd.get(13, 0);
30
    coffset = pd.get(2, 0);
31
    outw = pd.get(3, 0);
32
    outh = pd.get(4, 0);
33
    outd = pd.get(14, 0);
34
    outc = pd.get(5, 0);
35
    woffset2 = pd.get(6, 0);
36
    hoffset2 = pd.get(7, 0);
37
    doffset2 = pd.get(15, 0);
38
    coffset2 = pd.get(8, 0);
39

40
    starts = pd.get(9, Mat());
41
    ends = pd.get(10, Mat());
42
    axes = pd.get(11, Mat());
43

44
    bool numpy_style_slice = !starts.empty() && !ends.empty();
45

46
    if (outw == 0 && outh == 0 && outd == 0 && outc == 0 && woffset2 == 0 && hoffset2 == 0 && doffset2 == 0 && coffset2 == 0 && !numpy_style_slice)
47
    {
48
        one_blob_only = false;
49
    }
50

51
    return 0;
52
}
53

54
template<typename T>
55
static void copy_cut_border_image(const Mat& src, Mat& dst, int top, int left)
56
{
57
    int w = dst.w;
58
    int h = dst.h;
59

60
    const T* ptr = src.row<T>(top) + left;
61
    T* outptr = dst; //.data;
62

63
    for (int y = 0; y < h; y++)
64
    {
65
        if (w < 12)
66
        {
67
            for (int x = 0; x < w; x++)
68
            {
69
                outptr[x] = ptr[x];
70
            }
71
        }
72
        else
73
        {
74
            memcpy(outptr, ptr, w * sizeof(T));
75
        }
76
        outptr += w;
77
        ptr += src.w;
78
    }
79
}
80

81
int Crop::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const
82
{
83
    int w = bottom_blob.w;
84
    int h = bottom_blob.h;
85
    int d = bottom_blob.d;
86
    int channels = bottom_blob.c;
87
    int dims = bottom_blob.dims;
88
    size_t elemsize = bottom_blob.elemsize;
89

90
    int _woffset, _hoffset, _doffset, _coffset;
91
    int _outw = -1, _outh = -1, _outd = -1, _outc;
92
    resolve_crop_roi(bottom_blob.shape(), _woffset, _hoffset, _doffset, _coffset, _outw, _outh, _outd, _outc);
93

94
    if (dims == 1)
95
    {
96
        if (_outw == w)
97
        {
98
            top_blob = bottom_blob;
99
            return 0;
100
        }
101

102
        top_blob.create(_outw, elemsize, opt.blob_allocator);
103
        if (top_blob.empty())
104
            return -100;
105

106
        if (elemsize == 1)
107
            copy_cut_border_image<signed char>(bottom_blob, top_blob, 0, _woffset);
108
        if (elemsize == 2)
109
            copy_cut_border_image<unsigned short>(bottom_blob, top_blob, 0, _woffset);
110
        if (elemsize == 4)
111
            copy_cut_border_image<float>(bottom_blob, top_blob, 0, _woffset);
112

113
        return 0;
114
    }
115

116
    if (dims == 2)
117
    {
118
        if (_outw == w && _outh == h)
119
        {
120
            top_blob = bottom_blob;
121
            return 0;
122
        }
123

124
        top_blob.create(_outw, _outh, elemsize, opt.blob_allocator);
125
        if (top_blob.empty())
126
            return -100;
127

128
        if (elemsize == 1)
129
            copy_cut_border_image<signed char>(bottom_blob, top_blob, _hoffset, _woffset);
130
        if (elemsize == 2)
131
            copy_cut_border_image<unsigned short>(bottom_blob, top_blob, _hoffset, _woffset);
132
        if (elemsize == 4)
133
            copy_cut_border_image<float>(bottom_blob, top_blob, _hoffset, _woffset);
134

135
        return 0;
136
    }
137

138
    if (dims == 3)
139
    {
140
        if (_outw == w && _outh == h && _outc == channels)
141
        {
142
            top_blob = bottom_blob;
143
            return 0;
144
        }
145

146
        const Mat bottom_blob_sliced = bottom_blob.channel_range(_coffset, _outc);
147

148
        if (_outw == w && _outh == h)
149
        {
150
            top_blob = bottom_blob_sliced.clone();
151
            if (top_blob.empty())
152
                return -100;
153

154
            return 0;
155
        }
156

157
        top_blob.create(_outw, _outh, _outc, elemsize, opt.blob_allocator);
158
        if (top_blob.empty())
159
            return -100;
160

161
        #pragma omp parallel for num_threads(opt.num_threads)
162
        for (int q = 0; q < _outc; q++)
163
        {
164
            const Mat m = bottom_blob_sliced.channel(q);
165
            Mat borderm = top_blob.channel(q);
166

167
            if (elemsize == 1)
168
                copy_cut_border_image<signed char>(m, borderm, _hoffset, _woffset);
169
            if (elemsize == 2)
170
                copy_cut_border_image<unsigned short>(m, borderm, _hoffset, _woffset);
171
            if (elemsize == 4)
172
                copy_cut_border_image<float>(m, borderm, _hoffset, _woffset);
173
        }
174

175
        return 0;
176
    }
177

178
    if (dims == 4)
179
    {
180
        if (_outw == w && _outh == h && _outd == d && _outc == channels)
181
        {
182
            top_blob = bottom_blob;
183
            return 0;
184
        }
185

186
        const Mat bottom_blob_sliced = bottom_blob.channel_range(_coffset, _outc);
187

188
        if (_outw == w && _outh == h && _outd == d)
189
        {
190
            top_blob = bottom_blob_sliced.clone();
191
            if (top_blob.empty())
192
                return -100;
193

194
            return 0;
195
        }
196

197
        top_blob.create(_outw, _outh, _outd, _outc, elemsize, opt.blob_allocator);
198
        if (top_blob.empty())
199
            return -100;
200

201
        #pragma omp parallel for num_threads(opt.num_threads)
202
        for (int q = 0; q < _outc; q++)
203
        {
204
            for (int z = 0; z < _outd; z++)
205
            {
206
                const Mat m = bottom_blob_sliced.channel(q).depth(z + _doffset);
207
                Mat borderm = top_blob.channel(q).depth(z);
208

209
                if (elemsize == 1)
210
                    copy_cut_border_image<signed char>(m, borderm, _hoffset, _woffset);
211
                if (elemsize == 2)
212
                    copy_cut_border_image<unsigned short>(m, borderm, _hoffset, _woffset);
213
                if (elemsize == 4)
214
                    copy_cut_border_image<float>(m, borderm, _hoffset, _woffset);
215
            }
216
        }
217

218
        return 0;
219
    }
220

221
    return 0;
222
}
223

224
int Crop::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
225
{
226
    const Mat& bottom_blob = bottom_blobs[0];
227
    const Mat& reference_blob = bottom_blobs[1];
228

229
    int w = bottom_blob.w;
230
    int h = bottom_blob.h;
231
    int d = bottom_blob.d;
232
    int channels = bottom_blob.c;
233
    int dims = bottom_blob.dims;
234
    size_t elemsize = bottom_blob.elemsize;
235

236
    Mat& top_blob = top_blobs[0];
237

238
    int _woffset, _hoffset, _doffset, _coffset = -1;
239
    int _outw = -1, _outh = -1, _outd = -1, _outc;
240
    if (woffset == -233)
241
    {
242
        resolve_crop_roi(bottom_blob.shape(), (const int*)reference_blob, _woffset, _hoffset, _doffset, _coffset, _outw, _outh, _outd, _outc);
243
    }
244
    else
245
    {
246
        resolve_crop_roi(bottom_blob.shape(), reference_blob.shape(), _woffset, _hoffset, _doffset, _coffset, _outw, _outh, _outd, _outc);
247
    }
248

249
    if (dims == 1)
250
    {
251
        if (_outw == w)
252
        {
253
            top_blob = bottom_blob;
254
            return 0;
255
        }
256

257
        top_blob.create(_outw, elemsize, opt.blob_allocator);
258
        if (top_blob.empty())
259
            return -100;
260

261
        if (elemsize == 1)
262
            copy_cut_border_image<signed char>(bottom_blob, top_blob, 0, _woffset);
263
        if (elemsize == 2)
264
            copy_cut_border_image<unsigned short>(bottom_blob, top_blob, 0, _woffset);
265
        if (elemsize == 4)
266
            copy_cut_border_image<float>(bottom_blob, top_blob, 0, _woffset);
267

268
        return 0;
269
    }
270

271
    if (dims == 2)
272
    {
273
        if (_outw == w && _outh == h)
274
        {
275
            top_blob = bottom_blob;
276
            return 0;
277
        }
278

279
        top_blob.create(_outw, _outh, elemsize, opt.blob_allocator);
280
        if (top_blob.empty())
281
            return -100;
282

283
        if (elemsize == 1)
284
            copy_cut_border_image<signed char>(bottom_blob, top_blob, _hoffset, _woffset);
285
        if (elemsize == 2)
286
            copy_cut_border_image<unsigned short>(bottom_blob, top_blob, _hoffset, _woffset);
287
        if (elemsize == 4)
288
            copy_cut_border_image<float>(bottom_blob, top_blob, _hoffset, _woffset);
289

290
        return 0;
291
    }
292

293
    if (dims == 3)
294
    {
295
        if (_outw == w && _outh == h && _outc == channels)
296
        {
297
            top_blob = bottom_blob;
298
            return 0;
299
        }
300

301
        const Mat bottom_blob_sliced = bottom_blob.channel_range(_coffset, _outc);
302

303
        if (_outw == w && _outh == h)
304
        {
305
            top_blob = bottom_blob_sliced.clone();
306
            if (top_blob.empty())
307
                return -100;
308

309
            return 0;
310
        }
311

312
        top_blob.create(_outw, _outh, _outc, elemsize, opt.blob_allocator);
313
        if (top_blob.empty())
314
            return -100;
315

316
        #pragma omp parallel for num_threads(opt.num_threads)
317
        for (int q = 0; q < _outc; q++)
318
        {
319
            const Mat m = bottom_blob_sliced.channel(q);
320
            Mat borderm = top_blob.channel(q);
321

322
            if (elemsize == 1)
323
                copy_cut_border_image<signed char>(m, borderm, _hoffset, _woffset);
324
            if (elemsize == 2)
325
                copy_cut_border_image<unsigned short>(m, borderm, _hoffset, _woffset);
326
            if (elemsize == 4)
327
                copy_cut_border_image<float>(m, borderm, _hoffset, _woffset);
328
        }
329

330
        return 0;
331
    }
332

333
    if (dims == 4)
334
    {
335
        if (_outw == w && _outh == h && _outd == d && _outc == channels)
336
        {
337
            top_blob = bottom_blob;
338
            return 0;
339
        }
340

341
        const Mat bottom_blob_sliced = bottom_blob.channel_range(_coffset, _outc);
342

343
        if (_outw == w && _outh == h && _outd == d)
344
        {
345
            top_blob = bottom_blob_sliced.clone();
346
            if (top_blob.empty())
347
                return -100;
348

349
            return 0;
350
        }
351

352
        top_blob.create(_outw, _outh, _outd, _outc, elemsize, opt.blob_allocator);
353
        if (top_blob.empty())
354
            return -100;
355

356
        #pragma omp parallel for num_threads(opt.num_threads)
357
        for (int q = 0; q < _outc; q++)
358
        {
359
            for (int z = 0; z < _outd; z++)
360
            {
361
                const Mat m = bottom_blob_sliced.channel(q).depth(z + _doffset);
362
                Mat borderm = top_blob.channel(q).depth(z);
363

364
                if (elemsize == 1)
365
                    copy_cut_border_image<signed char>(m, borderm, _hoffset, _woffset);
366
                if (elemsize == 2)
367
                    copy_cut_border_image<unsigned short>(m, borderm, _hoffset, _woffset);
368
                if (elemsize == 4)
369
                    copy_cut_border_image<float>(m, borderm, _hoffset, _woffset);
370
            }
371
        }
372

373
        return 0;
374
    }
375

376
    return 0;
377
}
378

379
void Crop::resolve_crop_roi(const Mat& bottom_blob, int& _woffset, int& _hoffset, int& _doffset, int& _coffset, int& _outw, int& _outh, int& _outd, int& _outc) const
380
{
381
    int w = bottom_blob.w;
382
    int h = bottom_blob.h;
383
    int d = bottom_blob.d;
384
    int channels = bottom_blob.c;
385
    int dims = bottom_blob.dims;
386

387
    bool numpy_style_slice = !starts.empty() && !ends.empty();
388
    if (numpy_style_slice)
389
    {
390
        _woffset = 0;
391
        _hoffset = 0;
392
        _doffset = 0;
393
        _coffset = 0;
394
        _outw = w;
395
        _outh = h;
396
        _outd = d;
397
        _outc = channels;
398

399
        const int* starts_ptr = starts;
400
        const int* ends_ptr = ends;
401
        const int* axes_ptr = axes;
402

403
        int _axes[4] = {0, 1, 2, 3};
404
        int num_axis = axes.w;
405
        if (num_axis == 0)
406
        {
407
            num_axis = dims;
408
        }
409
        else
410
        {
411
            for (int i = 0; i < num_axis; i++)
412
            {
413
                int axis = axes_ptr[i];
414
                if (axis < 0)
415
                    axis = dims + axis;
416
                _axes[i] = axis;
417
            }
418
        }
419

420
        for (int i = 0; i < num_axis; i++)
421
        {
422
            int axis = _axes[i];
423
            int start = starts_ptr[i];
424
            int end = ends_ptr[i];
425

426
            if (dims == 1) // axis == 0
427
            {
428
                if (start == -233) start = 0;
429
                if (end == -233) end = w;
430
                _woffset = start >= 0 ? start : w + start;
431
                _outw = std::min(w, end > 0 ? end : w + end) - _woffset;
432
            }
433
            if (dims == 2)
434
            {
435
                if (axis == 0)
436
                {
437
                    if (start == -233) start = 0;
438
                    if (end == -233) end = h;
439
                    _hoffset = start >= 0 ? start : h + start;
440
                    _outh = std::min(h, end > 0 ? end : h + end) - _hoffset;
441
                }
442
                if (axis == 1)
443
                {
444
                    if (start == -233) start = 0;
445
                    if (end == -233) end = w;
446
                    _woffset = start >= 0 ? start : w + start;
447
                    _outw = std::min(w, end > 0 ? end : w + end) - _woffset;
448
                }
449
            }
450
            if (dims == 3)
451
            {
452
                if (axis == 0)
453
                {
454
                    if (start == -233) start = 0;
455
                    if (end == -233) end = channels;
456
                    _coffset = start >= 0 ? start : channels + start;
457
                    _outc = std::min(channels, end > 0 ? end : channels + end) - _coffset;
458
                }
459
                if (axis == 1)
460
                {
461
                    if (start == -233) start = 0;
462
                    if (end == -233) end = h;
463
                    _hoffset = start >= 0 ? start : h + start;
464
                    _outh = std::min(h, end > 0 ? end : h + end) - _hoffset;
465
                }
466
                if (axis == 2)
467
                {
468
                    if (start == -233) start = 0;
469
                    if (end == -233) end = w;
470
                    _woffset = start >= 0 ? start : w + start;
471
                    _outw = std::min(w, end > 0 ? end : w + end) - _woffset;
472
                }
473
            }
474
            if (dims == 4)
475
            {
476
                if (axis == 0)
477
                {
478
                    if (start == -233) start = 0;
479
                    if (end == -233) end = channels;
480
                    _coffset = start >= 0 ? start : channels + start;
481
                    _outc = std::min(channels, end > 0 ? end : channels + end) - _coffset;
482
                }
483
                if (axis == 1)
484
                {
485
                    if (start == -233) start = 0;
486
                    if (end == -233) end = d;
487
                    _doffset = start >= 0 ? start : d + start;
488
                    _outd = std::min(d, end > 0 ? end : d + end) - _doffset;
489
                }
490
                if (axis == 2)
491
                {
492
                    if (start == -233) start = 0;
493
                    if (end == -233) end = h;
494
                    _hoffset = start >= 0 ? start : h + start;
495
                    _outh = std::min(h, end > 0 ? end : h + end) - _hoffset;
496
                }
497
                if (axis == 3)
498
                {
499
                    if (start == -233) start = 0;
500
                    if (end == -233) end = w;
501
                    _woffset = start >= 0 ? start : w + start;
502
                    _outw = std::min(w, end > 0 ? end : w + end) - _woffset;
503
                }
504
            }
505
        }
506
    }
507
    else
508
    {
509
        _woffset = woffset;
510
        _hoffset = hoffset;
511
        _doffset = doffset;
512
        _coffset = coffset;
513
        _outw = w;
514
        _outh = h;
515
        _outd = d;
516
        _outc = channels;
517

518
        if (dims == 1)
519
        {
520
            _outw = w - woffset - woffset2;
521
            if (outw != -233)
522
                _outw = std::min(outw, _outw);
523
        }
524
        if (dims == 2)
525
        {
526
            _outw = w - woffset - woffset2;
527
            if (outw != -233)
528
                _outw = std::min(outw, _outw);
529

530
            _outh = h - hoffset - hoffset2;
531
            if (outh != -233)
532
                _outh = std::min(outh, _outh);
533
        }
534
        if (dims == 3)
535
        {
536
            _outw = w - woffset - woffset2;
537
            if (outw != -233)
538
                _outw = std::min(outw, _outw);
539

540
            _outh = h - hoffset - hoffset2;
541
            if (outh != -233)
542
                _outh = std::min(outh, _outh);
543

544
            _outc = channels - coffset - coffset2;
545
            if (outc != -233)
546
                _outc = std::min(outc, _outc);
547
        }
548
        if (dims == 4)
549
        {
550
            _outw = w - woffset - woffset2;
551
            if (outw != -233)
552
                _outw = std::min(outw, _outw);
553

554
            _outh = h - hoffset - hoffset2;
555
            if (outh != -233)
556
                _outh = std::min(outh, _outh);
557

558
            _outd = d - doffset - doffset2;
559
            if (outd != -233)
560
                _outd = std::min(outd, _outd);
561

562
            _outc = channels - coffset - coffset2;
563
            if (outc != -233)
564
                _outc = std::min(outc, _outc);
565
        }
566
    }
567
}
568

569
void Crop::resolve_crop_roi(const Mat& bottom_blob, const Mat& reference_blob, int& _woffset, int& _hoffset, int& _doffset, int& _coffset, int& _outw, int& _outh, int& _outd, int& _outc) const
570
{
571
    int channels = bottom_blob.c;
572
    int dims = bottom_blob.dims;
573

574
    int ref_w = reference_blob.w;
575
    int ref_h = reference_blob.h;
576
    int ref_d = reference_blob.d;
577
    int ref_channels = reference_blob.c;
578
    int ref_dims = reference_blob.dims;
579

580
    if (dims == 1)
581
    {
582
        _woffset = woffset;
583
        _outw = ref_w;
584
    }
585
    if (dims == 2)
586
    {
587
        _woffset = woffset;
588
        _hoffset = hoffset;
589
        _outw = ref_w;
590
        _outh = ref_h;
591
    }
592
    if (dims == 3)
593
    {
594
        _woffset = woffset;
595
        _hoffset = hoffset;
596
        _coffset = coffset;
597
        _outw = ref_w;
598
        _outh = ref_h;
599
        _outc = ref_dims == 3 ? ref_channels : channels;
600
    }
601
    if (dims == 4)
602
    {
603
        _woffset = woffset;
604
        _hoffset = hoffset;
605
        _doffset = doffset;
606
        _coffset = coffset;
607
        _outw = ref_w;
608
        _outh = ref_h;
609
        _outd = ref_d;
610
        _outc = ref_dims == 4 ? ref_channels : channels;
611
    }
612
}
613

614
void Crop::resolve_crop_roi(const Mat& bottom_blob, const int* param_data, int& _woffset, int& _hoffset, int& _doffset, int& _coffset, int& _outw, int& _outh, int& _outd, int& _outc) const
615
{
616
    int dims = bottom_blob.dims;
617

618
    if (dims == 1)
619
    {
620
        _woffset = param_data[0];
621
        _outw = param_data[3];
622
    }
623
    if (dims == 2)
624
    {
625
        _woffset = param_data[0];
626
        _hoffset = param_data[1];
627
        _outw = param_data[3];
628
        _outh = param_data[4];
629
    }
630
    if (dims == 3)
631
    {
632
        _woffset = param_data[0];
633
        _hoffset = param_data[1];
634
        _coffset = param_data[2];
635
        _outw = param_data[3];
636
        _outh = param_data[4];
637
        _outc = param_data[5];
638
    }
639
    if (dims == 4)
640
    {
641
        _woffset = param_data[0];
642
        _hoffset = param_data[1];
643
        _doffset = param_data[2];
644
        _coffset = param_data[3];
645
        _outw = param_data[4];
646
        _outh = param_data[5];
647
        _outd = param_data[6];
648
        _outc = param_data[7];
649
    }
650
}
651

652
} // namespace ncnn
653

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.