Edge Detection
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 22835 | Accepted: 5398 |
Description
IONU Satellite Imaging, Inc. records and stores very large images using run length encoding. You are to write a program that reads a compressed image, finds the edges in the image, as described below, and outputs another compressed image of the detected edges.
A simple edge detection algorithm sets an output pixel's value to be the maximum absolute value of the differences between it and all its surrounding pixels in the input image. Consider the input image below:
The upper left pixel in the output image is the maximum of the values |15-15|,|15-100|, and |15-100|, which is 85. The pixel in the 4th row, 2nd column is computed as the maximum of |175-100|, |175-100|, |175-100|, |175-175|, |175-25|, |175-175|,|175-175|, and |175-25|, which is 150.
Images contain 2 to 1,000,000,000 (109) pixels. All images are encoded using run length encoding (RLE). This is a sequence of pairs, containing pixel value (0-255) and run length (1-109). Input images have at most 1,000 of these pairs. Successive pairs have different pixel values. All lines in an image contain the same number of pixels.
A simple edge detection algorithm sets an output pixel's value to be the maximum absolute value of the differences between it and all its surrounding pixels in the input image. Consider the input image below:
The upper left pixel in the output image is the maximum of the values |15-15|,|15-100|, and |15-100|, which is 85. The pixel in the 4th row, 2nd column is computed as the maximum of |175-100|, |175-100|, |175-100|, |175-175|, |175-25|, |175-175|,|175-175|, and |175-25|, which is 150.
Images contain 2 to 1,000,000,000 (109) pixels. All images are encoded using run length encoding (RLE). This is a sequence of pairs, containing pixel value (0-255) and run length (1-109). Input images have at most 1,000 of these pairs. Successive pairs have different pixel values. All lines in an image contain the same number of pixels.
Input
Input
consists of information for one or more images. Each image starts with
the width, in pixels, of each image line. This is followed by the RLE
pairs, one pair per line. A line with 0 0 indicates the end of the data
for that image. An image width of 0 indicates there are no more images
to process. The first image in the example input encodes the 5x7 input
image above.
Output
Output
is a series of edge-detected images, in the same format as the input
images, except that there may be more than 1,000 RLE pairs.
Sample Input
7 15 4 100 15 25 2 175 2 25 5 175 2 25 5 0 0 10 35 500000000 200 500000000 0 0 3 255 1 10 1 255 2 10 1 255 2 10 1 255 1 0 0 0
Sample Output
7 85 5 0 2 85 5 75 10 150 2 75 3 0 2 150 2 0 4 0 0 10 0 499999990 165 20 0 499999990 0 0 3 245 9 0 0 0
Hint
A brute force solution that attempts to compute an output value for every individual pixel will likely fail due to space or time constraints.
Source
分析:
英文的题目,有点蛋疼,有几个限制数字理解错了意思,浪费了时间。
注意点:
1. 计算点不是上下左右4个点,而是周围8个点。
2. 每个点与左侧delta是前一个点与右侧的delta,不需要重复计算。
3. 行可以很长很长,注意long。
4. 每组input可以长为1000,而不是256。
5. 处理采用输入一组处理一组,循环处理。
6. 需要采用快进处理:1)多行相同;2)同一行相同数字很多。(考虑了最简单场景)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define MAX_POINT_SERIES_NUM 1000 6 7 #define FAILURE (int)0xF 8 #define SUCCESS (int)0x0 9 10 #define TRUE (int)1 11 #define FALSE (int)0 12 13 #define MIN(a, b) (((a) < (b))?(a):(b)) 14 #define MAX(a, b) (((a) > (b))?(a):(b)) 15 16 typedef int BOOL; 17 18 typedef struct 19 { 20 int value; 21 long long num; 22 long long startIdx; 23 long long endIdx; 24 }PointSeries; 25 26 typedef struct 27 { 28 long long imageWide; 29 int pointsNum; 30 long long endIdx; 31 PointSeries points[MAX_POINT_SERIES_NUM]; 32 }Image; 33 34 Image g_input; 35 Image g_output; 36 37 int GetInputImage(Image *input) 38 { 39 int i = 0; 40 long long idx = 0; 41 PointSeries *points = NULL; 42 43 scanf("%I64d", &input->imageWide); 44 if(0 == input->imageWide) 45 { 46 printf("0\n"); 47 return FAILURE; 48 } 49 50 do 51 { 52 points = &input->points[i]; 53 scanf("%d %I64d", &points->value, &points->num); 54 points->startIdx = idx; 55 points->endIdx = idx + points->num - 1; 56 idx = idx + points->num; 57 i++; 58 }while(points->num != 0 && MAX_POINT_SERIES_NUM <= i); 59 60 input->endIdx = input->points[i-1].endIdx; 61 62 input->pointsNum = i; 63 return SUCCESS; 64 } 65 66 void PrintImage(Image *image) 67 { 68 int i; 69 printf("%I64d\n", image->imageWide); 70 for(i = 0; i < image->pointsNum; i++) 71 { 72 printf("%d %I64d\n", 73 image->points[i].value, 74 image->points[i].num); 75 } 76 if(image->imageWide != 0) printf("0 0\n"); 77 } 78 79 static int GetLeftDelta(long long wide, PointSeries *points, long long idx, PointSeries *cmpPoints) 80 { 81 PointSeries *lastPoints = NULL; 82 long long lastIdx = idx - 1; 83 84 if(idx % wide != 0 85 && lastIdx >= 0 86 && lastIdx < points->startIdx) 87 { 88 lastPoints = points-1; 89 return abs(lastPoints->value - cmpPoints->value); 90 } 91 92 return 0; 93 } 94 95 static int GetRightDelta(Image *input, PointSeries *points, long long idx, PointSeries *cmpPoints) 96 { 97 PointSeries *nextPoints = NULL; 98 long long nextIdx = idx + 1; 99 100 if(idx % input->imageWide != input->imageWide - 1 101 && points->endIdx < input->endIdx 102 && nextIdx > points->endIdx) 103 { 104 nextPoints = points+1; 105 return abs(nextPoints->value - cmpPoints->value); 106 } 107 108 return 0; 109 } 110 111 static int GetPointSeries(long long idx, long long endIdx, PointSeries **targetPoints) 112 { 113 PointSeries *points = (*targetPoints); 114 if(idx < 0 || idx > endIdx) return FAILURE; 115 116 while(1) 117 { 118 if(idx <= points->endIdx && points->startIdx <= idx) break; 119 120 if(idx > points->endIdx) 121 { 122 points++; 123 } 124 else if(idx < points->startIdx) 125 { 126 points--; 127 } 128 } 129 130 *targetPoints = points; 131 132 return SUCCESS; 133 } 134 135 static int GetOtherLineDelta(Image *input, PointSeries *orgPoints, long long idx) 136 { 137 int leftDelta, rightDelta, delta; 138 PointSeries *target = orgPoints; 139 140 if(FAILURE == GetPointSeries(idx, input->endIdx, &target)) return 0; 141 142 leftDelta = GetLeftDelta(input->imageWide, target, idx, orgPoints); 143 rightDelta = GetRightDelta(input, target, idx, orgPoints); 144 delta = abs(target->value - orgPoints->value); 145 146 delta = MAX(delta , leftDelta); 147 delta = MAX(delta , rightDelta); 148 149 return delta; 150 } 151 152 void SaveOutput(Image *output, int delta, long long num) 153 { 154 PointSeries *points = &output->points[output->pointsNum]; 155 156 if(num == 0) return; 157 158 if(output->pointsNum == 0) 159 { 160 points->num = num; 161 points->value = delta; 162 output->pointsNum = 1; 163 return; 164 } 165 166 if((points-1)->value != delta) 167 { 168 points->num = num; 169 points->value = delta; 170 output->pointsNum++; 171 } 172 else 173 { 174 (points-1)->num += num; 175 } 176 } 177 178 void ProcPoints(Image *input, PointSeries *points, long long num, int *rightDelta, long long *idx, Image *output) 179 { 180 long long j; 181 long long tmpIdx = *idx; 182 int leftDelta, upDelta, dowmDelta, delta; 183 int tmpRight = *rightDelta; 184 185 for(j = 0; j < num; j++) 186 { 187 leftDelta = tmpRight; 188 tmpRight = GetRightDelta(input, points, tmpIdx, points); 189 upDelta = GetOtherLineDelta(input, points, tmpIdx - input->imageWide); 190 dowmDelta = GetOtherLineDelta(input, points, tmpIdx + input->imageWide); 191 delta = MAX(leftDelta, tmpRight); 192 delta = MAX(delta, upDelta); 193 delta = MAX(delta, dowmDelta); 194 SaveOutput(output, delta, 1); 195 tmpIdx++; 196 } 197 *idx = tmpIdx; 198 *rightDelta = tmpRight; 199 } 200 201 void RowFastForward(Image *input, PointSeries *points, int *rightDelta, long long *idx, Image *output) 202 { 203 long long firstNum, secondNum, thridNum; 204 long long endIdx; 205 long long wide = input->imageWide; 206 207 if(*idx % wide == 0) 208 firstNum = wide; 209 else 210 firstNum = wide + 1; 211 212 ProcPoints(input, points, firstNum, rightDelta, idx, output); 213 214 if(points->endIdx % wide == wide - 1) 215 endIdx = points->endIdx - wide; 216 else 217 endIdx = points->endIdx - wide - 1; 218 219 secondNum = endIdx + 1 - points->startIdx - firstNum; 220 thridNum = points->endIdx - endIdx; 221 222 SaveOutput(output, 0, secondNum); 223 *idx += secondNum; 224 225 ProcPoints(input, points, thridNum, rightDelta, idx, output); 226 } 227 228 inline BOOL CanBeRowFastForward(long long pointsNum, long long imageWide) 229 { 230 if(pointsNum >= 4 * imageWide - 1) 231 { 232 return TRUE; 233 } 234 else 235 { 236 return FALSE; 237 } 238 } 239 240 inline BOOL CanBeSpecFastForward(PointSeries *points, long long wide) 241 { 242 if(points->num == 0 243 || points->num / wide == 0 244 || points->num % wide != 0 245 || (points+1)->num % wide != 0) 246 { 247 return FALSE; 248 } 249 return TRUE; 250 } 251 252 void SpecFastForward(PointSeries *points, long long wide, int *specDelta, Image *output) 253 { 254 int tmpDeta = *specDelta; 255 long long num, lineNum = points->num / wide; 256 257 num = (lineNum > 1) ? wide : 0; 258 259 SaveOutput(output, tmpDeta, num); 260 261 num = (lineNum > 2) ? ((lineNum - 2)*wide) : 0; 262 263 SaveOutput(output, 0, num); 264 265 if((points+1)->num != 0 && lineNum == 1) 266 { 267 tmpDeta = MAX(abs(points->value - (points+1)->value), tmpDeta); 268 } 269 else if((points+1)->num != 0 && lineNum > 1) 270 { 271 tmpDeta = abs(points->value - (points+1)->value); 272 } 273 else if((points+1)->num == 0 && lineNum > 1) 274 { 275 tmpDeta = 0; 276 } 277 278 SaveOutput(output, tmpDeta, wide); 279 280 *specDelta = tmpDeta; 281 } 282 283 void ProcImage(Image *input, Image *output) 284 { 285 long long i = 0, idx = 0; 286 int rightDelta = 0; 287 int specDelta = 0; 288 PointSeries *points = &input->points[0]; 289 290 if(input->pointsNum == 0) return; 291 292 while(CanBeSpecFastForward(points, input->imageWide)) 293 { 294 SpecFastForward(points, input->imageWide, &specDelta, output); 295 points++; 296 i++; 297 } 298 299 for(; i < input->pointsNum; i++) 300 { 301 points = &input->points[i]; 302 303 if(points->num <= 0) continue; 304 305 if(CanBeRowFastForward(points->num, input->imageWide)) 306 { 307 RowFastForward(input, points, &rightDelta, &idx, output); 308 } 309 else 310 { 311 ProcPoints(input, points, points->num, &rightDelta, &idx, output); 312 } 313 } 314 } 315 316 inline void InitOutputBuf(Image *input, Image *output) 317 { 318 output->pointsNum = 0; 319 output->imageWide = input->imageWide; 320 } 321 322 int main() 323 { 324 while(SUCCESS == GetInputImage(&g_input)) 325 { 326 InitOutputBuf(&g_input, &g_output); 327 ProcImage(&g_input, &g_output); 328 PrintImage(&g_output); 329 } 330 331 return 0; 332 }