1 /******************************************************************************
2 * Copyright (c) 2018 Texas Instruments Incorporated - http://www.ti.com/
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Texas Instruments Incorporated nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *****************************************************************************/
29 #include <iostream>
30 #include "imgutil.h"
32 #include "opencv2/imgproc.hpp"
33 using namespace tidl;
34 using namespace cv;
36 bool tidl::imgutil::PreprocessImage(Mat& image, char *ptr,
37 const Configuration& c)
38 {
39 int num_channels = c.inNumChannels;
40 int output_width = c.inWidth;
41 int output_height = c.inHeight;
42 int pitch = c.inWidth;
43 int chOffset = c.inWidth * c.inHeight;
44 int preProcType = c.preProcType;
46 bool enableMeanSub = false;
47 Mat tempImage;
48 int32_t meanValues[num_channels];
50 if(preProcType == 0) // Caffe-Jacinto Models
51 {
52 int32_t half_the_width = 256/ 2;
53 int32_t half_the_height = 256/ 2;
55 int32_t startX = half_the_width - output_width/2;
56 int32_t startY = half_the_height - output_height/2;
58 cv::resize(image, tempImage, Size(256,256), 0,0,cv::INTER_AREA);
60 cv::Rect myROI(startX, startY, output_width, output_height);
61 image = tempImage(myROI);
63 enableMeanSub = false;
64 }
65 else if (preProcType == 1) // Caffe Models , eg : SqueezeNet
66 {
67 int32_t half_the_width = 256/ 2;
68 int32_t half_the_height = 256/ 2;
70 int32_t startX = half_the_width - output_width/2;
71 int32_t startY = half_the_height - output_height/2;
73 cv::resize(image, tempImage, Size(256,256), 0,0,cv::INTER_AREA);
75 cv::Rect myROI(startX, startY, output_width, output_height);
76 image = tempImage(myROI);
78 enableMeanSub = true;
79 meanValues[0] = 104;
80 meanValues[1] = 117;
81 meanValues[2] = 123;
83 }
84 // See https://github.com/tensorflow/models/blob/82e783e3172f254b62dc4af08987754ebb7c348c/research/slim/preprocessing/inception_preprocessing.py#L244
85 else if (preProcType == 2) // mobileNet, inceptionNet
86 {
87 cv::cvtColor(image, image, CV_BGR2RGB);
88 float factor = 0.875; // From TF preprocess_for_eval
89 int32_t orgWidth = image.size[1];
90 int32_t orgHeight = image.size[0];
92 int32_t crop_width = orgWidth*factor;
93 int32_t crop_height = orgHeight*factor;
94 int32_t half_the_width = orgWidth/ 2;
95 int32_t half_the_height = orgHeight / 2;
97 int32_t startX = half_the_width - crop_width/2;
98 int32_t startY = half_the_height - crop_height/2;
100 cv::Rect myROI(startX, startY, crop_width, crop_height);
101 tempImage = image(myROI);
103 cv::resize(tempImage, image, Size(output_width,output_height),
104 0, 0, CV_INTER_AREA);
106 enableMeanSub = true;
107 meanValues[0] = 128;
108 meanValues[1] = 128;
109 meanValues[2] = 128;
110 }
111 else if (preProcType == 3) // CIFAR 10
112 {
113 cv::cvtColor(image, image, CV_BGR2RGB);
114 int32_t half_the_width = 32/ 2;
115 int32_t half_the_height = 32/ 2;
117 int32_t startX = half_the_width - output_width/2;
118 int32_t startY = half_the_height - output_height/2;
121 cv::resize(image, tempImage, Size(32,32), 0,0,cv::INTER_AREA);
122 cv::Rect myROI(startX, startY, output_width, output_height);
123 image = tempImage(myROI);
124 enableMeanSub = false;
125 }
126 else if (preProcType == 4) // JdetNet
127 {
128 cv::resize(image, tempImage, Size(output_width,output_height),
129 0, 0, cv::INTER_AREA);
130 enableMeanSub = false;
131 }
132 else
133 {
134 std::cerr << "Unsupported preProcType : " << preProcType << std::endl;
135 return false;
136 }
138 if (image.channels() > 3)
139 return false;
141 if (image.total() != (unsigned int) (output_height * output_width))
142 return false;
144 Mat spl[num_channels];
145 split(image,spl);
147 for(int c = 0; c < num_channels; c++)
148 {
149 const unsigned char* data = spl[c].ptr();
151 for(int rows = 0; rows < output_height; rows++)
152 for(int cols = 0; cols < output_width; cols++)
153 {
154 int32_t in = data[rows*output_width + cols];
156 if(enableMeanSub)
157 {
158 in -= meanValues[c];
160 if(in > 127) in = 127;
161 if(in < -128) in = -128;
162 }
164 ptr[c*chOffset + rows*pitch + cols] = in;
165 }
166 }
168 return true;
169 }