Changeset 15321
- Timestamp:
- Oct 16, 2007, 3:49:12 PM (19 years ago)
- Location:
- trunk/psLib/src/imageops
- Files:
-
- 2 edited
-
psImageConvolve.c (modified) (7 diffs)
-
psImageConvolve.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/imageops/psImageConvolve.c
r15320 r15321 7 7 /// @author Eugene Magnier, IfA 8 8 /// 9 /// @version $Revision: 1.5 8$ $Name: not supported by cvs2svn $10 /// @date $Date: 2007-10-1 6 23:31:03$9 /// @version $Revision: 1.59 $ $Name: not supported by cvs2svn $ 10 /// @date $Date: 2007-10-17 01:49:12 $ 11 11 /// 12 12 /// Copyright 2004-2007 Institute for Astronomy, University of Hawaii … … 61 61 { 62 62 // Check the inputs to make sure max > min; if not, switch. 63 // following is explicitly spelled out in the SDRS as a requirement 63 64 if (yMin > yMax) { 64 psLogMsg(__func__, PS_LOG_WARN, 65 "Specified yMin, %d, was greater than yMax, %d. Values swapped.", 65 psWarning("Specified yMin, %d, was greater than yMax, %d. Values swapped.", 66 66 yMin, yMax); 67 67 … … 70 70 yMax = temp; 71 71 } 72 73 // following is explicitly spelled out in the SDRS as a requirement74 72 if (xMin > xMax) { 75 psLogMsg(__func__, PS_LOG_WARN, 76 "Specified xMin, %d, was greater than xMax, %d. Values swapped.", 73 psWarning("Specified xMin, %d, was greater than xMax, %d. Values swapped.", 77 74 xMin, xMax); 78 75 … … 313 310 } 314 311 315 psImage *psImageConvolveMaskDirect(const psImage *mask, psMaskType maskVal, const psKernel *kernel) 312 psImage *psImageConvolveMaskDirect(psImage *out, const psImage *mask, psMaskType maskVal, 313 psMaskType setVal, int xMin, int xMax, int yMin, int yMax) 316 314 { 317 315 PS_ASSERT_IMAGE_NON_NULL(mask, NULL); 318 316 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL); 319 PS_ASSERT_PTR_NON_NULL(kernel, NULL); 320 PS_ASSERT_PTR_NON_NULL(kernel->kernel, NULL); 321 322 // Pull out kernel parameters, for convenience 323 int xMin = kernel->xMin; 324 int xMax = kernel->xMax; 325 int yMin = kernel->yMin; 326 int yMax = kernel->yMax; 317 if (out == mask && ((maskVal & setVal) || !setVal)) { 318 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 319 "Can't convolve mask in-place if values to set contains values to convolve."); 320 return NULL; 321 } 322 323 if (yMin > yMax) { 324 psWarning("Specified yMin, %d, was greater than yMax, %d. Values swapped.", 325 yMin, yMax); 326 327 int temp = yMin; 328 yMin = yMax; 329 yMax = temp; 330 } 331 if (xMin > xMax) { 332 psWarning("Specified xMin, %d, was greater than xMax, %d. Values swapped.", 333 xMin, xMax); 334 335 int temp = xMin; 336 xMin = xMax; 337 xMax = temp; 338 } 327 339 328 340 int numRows = mask->numRows; // Number of rows 329 341 int numCols = mask->numCols; // Number of columns 330 342 331 psImage *out = psImageAlloc(numCols, numRows, PS_TYPE_MASK); // Output mask 343 if (!out) { 344 // Propagate the non-masked values 345 out = (psImage*)psBinaryOp(NULL, (const psPtr)mask, "&", psScalarAlloc(~maskVal, PS_TYPE_MASK)); 346 } 332 347 333 348 // Dereference mask images … … 335 350 psMaskType **outData = out->data.PS_TYPE_MASK_DATA; 336 351 337 // Propagate the non-masked values 338 for (int row = 0; row < numRows; row++) { 339 for (int col = 0; col < numCols; col++) { 340 outData[row][col] = maskData[row][col] & ~maskVal; 341 } 342 } 343 344 for (int row = 0; row < numRows; row++) { 345 for (int col = 0; col < numCols; col++) { 346 if (maskData[row][col] & maskVal) { 347 // It's already masked --- move on 348 continue; 349 } 350 psMaskType pixel = 0; // New pixel value 351 for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) { 352 for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) { 353 pixel |= maskData[row + kRow][col + kCol] & maskVal; 352 if (setVal) { 353 // Grow any pixels matching maskVal, setting setVal 354 for (int row = 0; row < numRows; row++) { 355 for (int col = 0; col < numCols; col++) { 356 if (maskData[row][col] & maskVal) { 357 for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) { 358 for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) { 359 outData[row + kRow][col + kCol] |= setVal; 360 } 361 } 354 362 } 355 363 } 356 outData[row][col] |= pixel; 364 } 365 } else { 366 // Each pixel receives any maskVal bits set within the convolution window 367 for (int row = 0; row < numRows; row++) { 368 for (int col = 0; col < numCols; col++) { 369 psMaskType pixel = outData[row][col]; // Pixel value to set 370 if (pixel & maskVal) { 371 // Already done this one 372 continue; 373 } 374 for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) { 375 for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) { 376 pixel |= maskData[row][col] & maskVal; 377 } 378 } 379 outData[row][col] = pixel; 380 } 357 381 } 358 382 } … … 494 518 495 519 496 psImage *psImageConvolveMaskFFT(const psImage *mask, psMaskType maskVal, const psKernel *kernel, float thresh) 520 psImage *psImageConvolveMaskFFT(psImage *out, const psImage *mask, psMaskType maskVal, 521 psMaskType setVal, int xMin, int xMax, int yMin, int yMax, float thresh) 497 522 { 498 523 PS_ASSERT_IMAGE_NON_NULL(mask, NULL); 499 524 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL); 500 PS_ASSERT_PTR_NON_NULL(kernel, NULL);501 PS_ASSERT_PTR_NON_NULL(kernel->kernel, NULL);502 525 PS_ASSERT_FLOAT_LARGER_THAN(thresh, 0.0, NULL); 503 526 PS_ASSERT_FLOAT_LESS_THAN(thresh, 1.0, NULL); 527 if (out == mask && (maskVal & setVal)) { 528 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 529 "Can't convolve mask in-place if values to set contains values to convolve."); 530 return NULL; 531 } 532 533 if (yMin > yMax) { 534 psWarning("Specified yMin, %d, was greater than yMax, %d. Values swapped.", 535 yMin, yMax); 536 537 int temp = yMin; 538 yMin = yMax; 539 yMax = temp; 540 } 541 if (xMin > xMax) { 542 psWarning("Specified xMin, %d, was greater than xMax, %d. Values swapped.", 543 xMin, xMax); 544 545 int temp = xMin; 546 xMin = xMax; 547 xMax = temp; 548 } 504 549 505 550 int numRows = mask->numRows, numCols = mask->numCols; // Size of image 506 551 507 psImage *onoff = (psImage*)psBinaryOp(NULL, (const psPtr)mask, "&", // Casting away const so I can use 508 psScalarAlloc(maskVal, PS_TYPE_MASK)); // Pixels on or off 509 psImage *copy = psImageCopy(NULL, onoff, PS_TYPE_F32); // Floating-point copy 510 psImage *convolved = psImageConvolveFFT(copy, NULL, 0, kernel, 0.0); 511 psFree(copy); 512 513 thresh *= maskVal; 552 if (!psMemIncrRefCounter(out)) { 553 out = psImageAlloc(numCols, numRows, PS_TYPE_MASK); 554 } 555 556 psImage *onoff = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Pixels on or off 557 psImageInit(onoff, 0); 514 558 for (int y = 0; y < numRows; y++) { 515 559 for (int x = 0; x < numCols; x++) { 516 onoff->data.PS_TYPE_MASK_DATA[y][x] = (convolved->data.F32[y][x] >= thresh) ? 517 (mask->data.PS_TYPE_MASK_DATA[y][x] | maskVal) : mask->data.PS_TYPE_MASK_DATA[y][x]; 560 if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) { 561 onoff->data.F32[y][x] = 1.0; 562 } 563 } 564 } 565 566 psKernel *kernel = psKernelAlloc(xMin, xMax, yMin, yMax); 567 psImageInit(kernel->image, 1.0); 568 psImage *convolved = psImageConvolveFFT(onoff, NULL, 0, kernel, 0.0); 569 psFree(onoff); 570 psFree(kernel); 571 if (!convolved) { 572 psError(PS_ERR_UNKNOWN, false, "Unable to convolve mask."); 573 psFree(out); 574 return NULL; 575 } 576 577 thresh *= maskVal; 578 579 if (!setVal) { 580 setVal = maskVal; 581 } 582 583 for (int y = 0; y < numRows; y++) { 584 for (int x = 0; x < numCols; x++) { 585 out->data.PS_TYPE_MASK_DATA[y][x] = (convolved->data.F32[y][x] >= thresh) ? 586 (mask->data.PS_TYPE_MASK_DATA[y][x] | setVal) : mask->data.PS_TYPE_MASK_DATA[y][x]; 518 587 } 519 588 } … … 521 590 psFree(convolved); 522 591 523 return o noff;592 return out; 524 593 } 525 594 -
trunk/psLib/src/imageops/psImageConvolve.h
r15320 r15321 5 5 * @author Robert DeSonia, MHPCC 6 6 * 7 * @version $Revision: 1.3 0$ $Name: not supported by cvs2svn $8 * @date $Date: 2007-10-1 6 23:31:03$7 * @version $Revision: 1.31 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2007-10-17 01:49:12 $ 9 9 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 10 10 */ … … 155 155 /// Convolve a mask image with a kernel, using direct convolution 156 156 /// 157 /// Returns a mask, grown by the supplied kernel. Only those pixels specified by the maskVal are grown; the 158 /// rest are simply propagated. 159 psImage *psImageConvolveMaskDirect(const psImage *mask, ///< Mask to convolve 157 /// Returns a mask, grown by the supplied convolution bounds. Only those pixels specified by the maskVal are 158 /// grown, being ORed with setVal; the rest are simply propagated. If setVal is zero, then individual bits 159 /// matching maskVal are grown. 160 psImage *psImageConvolveMaskDirect(psImage *out, ///< Output image, or NULL 161 const psImage *mask, ///< Mask to convolve 160 162 psMaskType maskVal, ///< Mask value to convolve 161 const psKernel *kernel ///< Kernel by which to convolve 163 psMaskType setVal, ///< Mask value to set; 0 to propagate maskVal 164 int xMin, int xMax, int yMin, int yMax ///< Convolution bounds 162 165 ); 163 166 164 167 /// Convolve a mask image with a kernel, using the FFT 165 168 /// 166 /// Returns a mask, grown by the supplied kernel. Only those pixels specified by the maskVal are grown; the 167 /// rest are simply propagated. Uses psImageConvolveFFT to convolve the mask, and then thresholds at the 168 /// specified level. 169 psImage *psImageConvolveMaskFFT(const psImage *mask, ///< Mask to convolve 169 /// Returns a mask, grown by the supplied convolution bounds. Only those pixels specified by the maskVal are 170 /// grown, being ORed with setVal; the rest are simply propagated. If setVal is zero, uses maskVal; note that 171 /// the mode of growing individual bits in maskVal is NOT supported because this algorithm does not enable it. 172 /// Uses psImageConvolveFFT to convolve those pixels which are masked, and then thresholds at the specified 173 /// level. 174 psImage *psImageConvolveMaskFFT(psImage *out, ///< Output image, or NULL 175 const psImage *mask, ///< Mask to convolve 170 176 psMaskType maskVal, ///< Mask value to convolve 171 const psKernel *kernel, ///< Kernel by which to convolve 177 psMaskType setVal, ///< Mask value to set; 0 to use maskVal 178 int xMin, int xMax, int yMin, int yMax, ///< Convolution bounds 172 179 float thresh ///< Threshold (0..1) for convolved floating-point image 173 180 ); 174 175 181 176 182 /// Smooths an image by parts using 1D Gaussian independently in x and y.
Note:
See TracChangeset
for help on using the changeset viewer.
