1 module dcv.features.corner.fast.nonmax; 2 3 /** 4 * Authors: Edward Rosten 5 * Copyright: Copyright (c) 2006, 2008 Edward Rosten, All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 12 * *Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * *Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * *Neither the name of the University of Cambridge nor the names of 20 * its contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 * Additional notice: 36 * Module integrates FAST implementation present in the Edward Rosten's 37 * github repository: https://github.com/edrosten/fast-C-src 38 */ 39 40 import core.stdc.stdlib : malloc, free, realloc; 41 42 import dcv.features.corner.fast.base; 43 44 alias Compare = (X, Y) => (X>=Y); 45 46 47 xy* nonmax_suppression(const xy* corners, const int* scores, int num_corners, int* ret_num_nonmax) 48 { 49 int num_nonmax=0; 50 int last_row; 51 int* row_start; 52 int i, j; 53 xy* ret_nonmax; 54 const int sz = cast(int)num_corners; 55 56 /*Point above points (roughly) to the pixel above the one of interest, if there 57 is a feature there.*/ 58 int point_above = 0; 59 int point_below = 0; 60 61 62 if(num_corners < 1) 63 { 64 *ret_num_nonmax = 0; 65 return null; 66 } 67 68 ret_nonmax = cast(xy*)malloc(num_corners * xy.sizeof); 69 70 /* Find where each row begins 71 (the corners are output in raster scan order). A beginning of -1 signifies 72 that there are no corners on that row. */ 73 last_row = corners[num_corners-1].y; 74 row_start = cast(int*)malloc((last_row+1)*int.sizeof); 75 76 for(i=0; i < last_row+1; i++) 77 row_start[i] = -1; 78 79 { 80 int prev_row = -1; 81 for(i=0; i< num_corners; i++) 82 if(corners[i].y != prev_row) 83 { 84 row_start[corners[i].y] = i; 85 prev_row = corners[i].y; 86 } 87 } 88 89 90 91 for(i=0; i < sz; i++) 92 { 93 int score = scores[i]; 94 xy pos = corners[i]; 95 96 /*Check left */ 97 if(i > 0) 98 if(corners[i-1].x == pos.x-1 && corners[i-1].y == pos.y && Compare(scores[i-1], score)) 99 continue; 100 101 /*Check right*/ 102 if(i < (sz - 1)) 103 if(corners[i+1].x == pos.x+1 && corners[i+1].y == pos.y && Compare(scores[i+1], score)) 104 continue; 105 106 /*Check above (if there is a valid row above)*/ 107 if(pos.y != 0 && row_start[pos.y - 1] != -1) 108 { 109 /*Make sure that current point_above is one 110 row above.*/ 111 if(corners[point_above].y < pos.y - 1) 112 point_above = row_start[pos.y-1]; 113 114 /*Make point_above point to the first of the pixels above the current point, 115 if it exists.*/ 116 for(; corners[point_above].y < pos.y && corners[point_above].x < pos.x - 1; point_above++) 117 {} 118 119 120 for(j=point_above; corners[j].y < pos.y && corners[j].x <= pos.x + 1; j++) 121 { 122 int x = corners[j].x; 123 if( (x == pos.x - 1 || x ==pos.x || x == pos.x+1) && Compare(scores[j], score)) 124 goto cont; 125 } 126 127 } 128 129 /*Check below (if there is anything below)*/ 130 if(pos.y != last_row && row_start[pos.y + 1] != -1 && point_below < sz) /*Nothing below*/ 131 { 132 if(corners[point_below].y < pos.y + 1) 133 point_below = row_start[pos.y+1]; 134 135 /* Make point below point to one of the pixels belowthe current point, if it 136 exists.*/ 137 for(; point_below < sz && corners[point_below].y == pos.y+1 && corners[point_below].x < pos.x - 1; point_below++) 138 {} 139 140 for(j=point_below; j < sz && corners[j].y == pos.y+1 && corners[j].x <= pos.x + 1; j++) 141 { 142 int x = corners[j].x; 143 if( (x == pos.x - 1 || x ==pos.x || x == pos.x+1) && Compare(scores[j],score)) 144 goto cont; 145 } 146 } 147 148 ret_nonmax[num_nonmax++] = corners[i]; 149 cont: 150 ; 151 } 152 153 free(row_start); 154 *ret_num_nonmax = num_nonmax; 155 return ret_nonmax; 156 }