Changeset 25337 for branches/pap/psLib/src/imageops/psImageConvolve.c
- Timestamp:
- Sep 10, 2009, 6:41:31 PM (17 years ago)
- File:
-
- 1 edited
-
branches/pap/psLib/src/imageops/psImageConvolve.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/pap/psLib/src/imageops/psImageConvolve.c
r24272 r25337 678 678 } 679 679 680 static bool imageSmoothMaskPixels(psVector *out, const psImage *image, const psImage *mask, 681 psImageMaskType maskVal, const psVector *x, const psVector *y, 682 const psVector *gaussNorm, float minGauss, int size, int start, int stop) 683 { 684 const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel 685 int numCols = image->numCols, numRows = image->numRows; // Size of image 686 int xLast = numCols - 1, yLast = numRows - 1; // Last index 687 for (int i = start; i < stop; i++) { 688 int xPix = x->data.S32[i], yPix = y->data.S32[i]; // Pixel coordinates for smoothing 689 690 int yMin = PS_MAX(yPix - size, 0); 691 int yMax = PS_MIN(yPix + size, yLast); 692 int xMin = PS_MAX(xPix - size, 0); 693 int xMax = PS_MIN(xPix + size, xLast); 694 695 const float *yGauss = &gauss[yMin - yPix]; 696 697 double ySumIG = 0.0, ySumG = 0.0; 698 for (int v = yMin; v <= yMax; v++, yGauss++) { 699 const float *xGauss = &gauss[xMin - xPix]; 700 double xSumIG = 0.0, xSumG = 0.0; 701 const psImageMaskType *maskData = &mask->data.PS_TYPE_IMAGE_MASK_DATA[v][xMin]; 702 const psF32 *imageData = &image->data.F32[v][xMin]; 703 for (int u = xMin; u <= xMax; u++, xGauss++, imageData++, maskData++) { 704 if (*maskData & maskVal) { 705 continue; 706 } 707 xSumIG += *imageData * *xGauss; 708 xSumG += *xGauss; 709 } 710 if (xSumG > minGauss) { 711 ySumIG += xSumIG * *yGauss; 712 ySumG += xSumG * *yGauss; 713 } 714 } 715 716 out->data.F32[i] = ySumG > minGauss ? ySumIG / ySumG : NAN; 717 } 718 719 return true; 720 } 721 722 static bool psImageSmoothMaskPixelsThread(psThreadJob *job) 723 { 724 PS_ASSERT_THREAD_JOB_NON_NULL(job, false); 725 psAssert(job->args, "programming error: no job arguments"); 726 psAssert(job->args->n == 11, "programming error: wrong number of job arguments"); 727 728 psVector *out = job->args->data[0]; // Output vector 729 const psImage *image = job->args->data[1]; // Input image 730 const psImage *mask = job->args->data[2]; // Input mask 731 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3], PS_TYPE_IMAGE_MASK_DATA); 732 const psVector *x = job->args->data[4]; 733 const psVector *y = job->args->data[5]; 734 const psVector *gaussNorm = job->args->data[6]; 735 float minGauss = PS_SCALAR_VALUE(job->args->data[7], F32); 736 int size = PS_SCALAR_VALUE(job->args->data[8], S32); 737 int start = PS_SCALAR_VALUE(job->args->data[9], S32); 738 int stop = PS_SCALAR_VALUE(job->args->data[10], S32); 739 return imageSmoothMaskPixels(out, image, mask, maskVal, x, y, gaussNorm, 740 minGauss, size, start, stop); 741 } 742 743 744 psVector *psImageSmoothMaskPixels(const psImage *image, const psImage *mask, psImageMaskType maskVal, 745 const psVector *x, const psVector *y, 746 float sigma, float numSigma, float minGauss) 747 { 748 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 749 PS_ASSERT_IMAGE_NON_NULL(mask, NULL); 750 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_IMAGE_MASK, NULL); 751 PS_ASSERT_IMAGES_SIZE_EQUAL(image, mask, NULL); 752 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 753 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_S32, NULL); 754 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 755 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_S32, NULL); 756 PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL); 757 758 int size = sigma * numSigma + 0.5; // Half-size of kernel 759 760 int num = x->n; // Number of pixels to smooth 761 psVector *out = psVectorAlloc(num, PS_TYPE_F32); // Output results 762 763 // Generate normalized gaussian 764 IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32); 765 766 // Columns 767 if (threaded) { 768 int numThreads = psThreadPoolSize(); // Number of threads 769 int delta = (numThreads) ? num / numThreads + 1 : num; // Block of cols to do at once 770 for (int start = 0; start < num; start += delta) { 771 int stop = PS_MIN(start + delta, num); // End of block 772 773 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS"); 774 psArrayAdd(job->args, 1, out); 775 psArrayAdd(job->args, 1, (psImage*)image); 776 psArrayAdd(job->args, 1, (psImage*)mask); 777 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 778 psArrayAdd(job->args, 1, (psVector*)x); 779 psArrayAdd(job->args, 1, (psVector*)y); 780 psArrayAdd(job->args, 1, gaussNorm); 781 PS_ARRAY_ADD_SCALAR(job->args, minGauss, PS_TYPE_F32); 782 PS_ARRAY_ADD_SCALAR(job->args, size, PS_TYPE_S32); 783 PS_ARRAY_ADD_SCALAR(job->args, start, PS_TYPE_S32); 784 PS_ARRAY_ADD_SCALAR(job->args, stop, PS_TYPE_S32); 785 if (!psThreadJobAddPending(job)) { 786 psFree(job); 787 psFree(gaussNorm); 788 psFree(out); 789 return NULL; 790 } 791 psFree(job); 792 } 793 } else if (!imageSmoothMaskPixels(out, image, mask, maskVal, x, y, 794 gaussNorm, minGauss, size, 0, num)) { 795 psError(PS_ERR_UNKNOWN, false, "Unable to smooth pixels."); 796 psFree(gaussNorm); 797 psFree(out); 798 return NULL; 799 } 800 801 if (threaded && !psThreadPoolWait(true)) { 802 psError(PS_ERR_UNKNOWN, false, "Error waiting for threads."); 803 psFree(gaussNorm); 804 psFree(out); 805 return NULL; 806 } 807 808 psFree(gaussNorm); 809 return out; 810 } 811 812 680 813 // Smooth an image with masked pixels 681 814 // The calculation and calcMask images are *deliberately* backwards (row,col instead of col,row or … … 1325 1458 if (threaded) { 1326 1459 int numThreads = psThreadPoolSize(); // Number of threads 1327 int deltaRows = (numThreads) ? numRows / numThreads : numRows; // Block of rows to do at once1460 int deltaRows = (numThreads) ? numRows / numThreads + 1 : numRows; // Block of rows to do at once 1328 1461 for (int start = 0; start < numRows; start += deltaRows) { 1329 int stop = PS_MIN (start + deltaRows, numRows); // end of row block1462 int stop = PS_MIN(start + deltaRows, numRows); // end of row block 1330 1463 1331 1464 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK"); … … 1363 1496 if (threaded) { 1364 1497 int numThreads = psThreadPoolSize(); // Number of threads 1365 int deltaCols = (numThreads) ? numCols / numThreads : numCols; // Block of cols to do at once1498 int deltaCols = (numThreads) ? numCols / numThreads + 1 : numCols; // Block of cols to do at once 1366 1499 for (int start = 0; start < numCols; start += deltaCols) { 1367 int stop = PS_MIN (start + deltaCols, numCols); // end of col block1500 int stop = PS_MIN(start + deltaCols, numCols); // end of col block 1368 1501 1369 1502 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK"); … … 1486 1619 psFree(task); 1487 1620 } 1621 { 1622 psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS", 9); 1623 task->function = &psImageSmoothMaskPixelsThread; 1624 psThreadTaskAdd(task); 1625 psFree(task); 1626 } 1488 1627 } else if (!set && threaded) { 1489 1628 psThreadTaskRemove("PSLIB_IMAGE_CONVOLVE_MASK");
Note:
See TracChangeset
for help on using the changeset viewer.
