1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma version(1) 18 #pragma rs java_package_name(com.example.android.rs.sample) 19 #pragma rs_fp_relaxed 20 rs_allocation tmp; 21 22 static rs_allocation createVectorAllocation(rs_data_type dt, int vecSize, 23 int gDimX, int gDimY, int gDimZ) { 24 rs_element element; 25 rs_type type; 26 27 if (vecSize == 1) 28 element = rsCreateElement(dt); 29 else 30 element = rsCreateVectorElement(dt, vecSize); 31 32 if (gDimY == 0) { 33 type = rsCreateType(element, gDimX); 34 } else { 35 type = rsCreateType(element, gDimX, gDimY, gDimZ); 36 } 37 tmp = rsCreateAllocation(type); 38 return tmp; 39 } 40 41 rs_allocation mImage; 42 int2 mImgOffset; 43 int2 mSearchOffset; // offset to the region we will search 44 rs_allocation mBorderValues; // float3 45 rs_allocation mBorderCoords; // int2 46 47 int mBorderLength; 48 int2 __attribute__((kernel)) toInt_ss(int2 in) { return in - mImgOffset; } 49 50 float3 __attribute__((kernel)) extractBorder_ss(uint2 in) { 51 return convert_float3(rsGetElementAt_uchar4(mImage, in.x, in.y).xyz); 52 } 53 54 static float4 gCalcBounds(rs_allocation xy) { 55 int len = rsAllocationGetDimX(xy); 56 float2 min_xy = rsGetElementAt_float2(xy, 0); 57 float2 max_xy = min_xy; 58 for (int i = 1; i < len; i++) { 59 float2 v = rsGetElementAt_float2(xy, i); 60 min_xy = min(min_xy, v); 61 max_xy = max(max_xy, v); 62 } 63 64 return (float4){min_xy.x, min_xy.y, max_xy.x, max_xy.y}; 65 } 66 67 uint2 __attribute__((kernel)) toInt(float2 in) { 68 return (uint2){(int)in.x, (int)in.y}; 69 } 70 71 static int4 padRegionRect_ss(float4 rec) { 72 int width = rec.z - rec.x; 73 int height = rec.w - rec.y; 74 int mWidth = 75 (((int)(8 + width)) & ~3); // bounding rectangle that is a power of 8 big 76 int mHeight = (((int)(8 + height)) & ~3); 77 int4 out = {(int)(rec.x - 1), (int)(rec.y - 1), mWidth + (int)(rec.x - 1), 78 mHeight + (int)(rec.y - 1)}; 79 return out; 80 } 81 82 static int4 calcSearchRange_ss(int4 roiBounds, int imgWidth, int imgHeight, 83 int pad) { 84 int2 size = roiBounds.zw - roiBounds.xy; 85 int2 minr = max((int2){0, 0}, roiBounds.xy - size * (1 + pad)); 86 int2 maxr = min((int2){imgWidth, imgHeight}, roiBounds.zw + size * (1 + pad)); 87 return (int4){minr.x, minr.y, maxr.x, maxr.y}; 88 } 89 90 float __attribute__((kernel)) bordercorrelation_ss(uint32_t x, uint32_t y) { 91 float sum = 0.f; 92 int2 delta = {x, y}; 93 delta += mSearchOffset; 94 95 for (int i = 0; i < mBorderLength; i++) { 96 int2 coord = rsGetElementAt_int2(mBorderCoords, i) + delta; 97 float3 orig = 98 convert_float3(rsGetElementAt_uchar4(mImage, coord.x, coord.y).xyz); 99 float3 candidate = rsGetElementAt_float3(mBorderValues, i).xyz; 100 sum += distance(orig, candidate); 101 } 102 return sum; 103 } 104 105 static int2 gfindMin_ss(rs_allocation fit, int4 regionInSearch) { 106 int w = rsAllocationGetDimX(fit); 107 int h = rsAllocationGetDimY(fit); 108 float minFit = rsGetElementAt_float(fit, 0, 0); 109 int2 fit_pos = {0, 0}; 110 111 for (int y = 0; y < h; y++) { 112 for (int x = 0; x < w; x++) { 113 int2 p = {x, y}; 114 p = (p - regionInSearch.xy) * 115 (p - regionInSearch.zw); // positive if outside of exclusion zone 116 if (!(p.x < 0 && p.y < 0)) { 117 float v = rsGetElementAt_float(fit, x, y); 118 if (v < minFit) { 119 minFit = v; 120 fit_pos.x = x; 121 fit_pos.y = y; 122 } 123 } 124 } 125 } 126 127 return fit_pos; 128 } 129 130 static int width(int4 rec) { return rec.z - rec.x; } 131 static int height(int4 rec) { return rec.w - rec.y; } 132 133 /** 134 * Entry point to frind region 135 */ 136 void findRegion(rs_allocation pointsXY, rs_allocation image, int imgWidth, 137 int imgHeight, rs_allocation ret) { 138 rs_allocation fit; 139 140 mImage = image; 141 142 mBorderLength = rsAllocationGetDimX(pointsXY); 143 144 float4 bounds = gCalcBounds(pointsXY); 145 146 int4 roiBounds = padRegionRect_ss(bounds); 147 148 int4 searchRange = calcSearchRange_ss(roiBounds, imgWidth, imgHeight, 2); 149 150 int4 regionInSearch = roiBounds - searchRange.xyxy; 151 152 mSearchOffset = searchRange.xy; 153 mImgOffset = roiBounds.xy; 154 155 mBorderCoords = 156 createVectorAllocation(RS_TYPE_SIGNED_32, 2, mBorderLength, 0, 0); 157 158 rsForEach(toInt, pointsXY, mBorderCoords); 159 160 mBorderValues = 161 createVectorAllocation(RS_TYPE_FLOAT_32, 3, mBorderLength, 0, 0); 162 163 rsForEach(extractBorder_ss, mBorderCoords, mBorderValues); 164 rsForEach(toInt_ss, mBorderCoords, mBorderCoords); 165 166 int fit_width = width(searchRange) - width(roiBounds); 167 int fit_height = height(searchRange) - height(roiBounds); 168 169 fit = createVectorAllocation(RS_TYPE_FLOAT_32, 1, fit_width, fit_height, 0); 170 171 int4 noZone = regionInSearch; 172 noZone.xy -= convert_int2(bounds.zw - bounds.xy); 173 noZone.zw += convert_int2(bounds.zw - bounds.xy); 174 175 rsForEach(bordercorrelation_ss, fit); 176 177 int2 fit_pos = gfindMin_ss(fit, noZone); 178 179 rsSetElementAt_int2(ret, fit_pos + searchRange.xy, 0); 180 } 181