Changeset 1863
- Timestamp:
- Sep 23, 2004, 8:30:57 AM (22 years ago)
- Location:
- trunk/psLib/src
- Files:
-
- 4 edited
-
image/psImageConvolve.c (modified) (9 diffs)
-
image/psImageConvolve.h (modified) (4 diffs)
-
imageops/psImageConvolve.c (modified) (9 diffs)
-
imageops/psImageConvolve.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/image/psImageConvolve.c
r1840 r1863 5 5 * @author Robert DeSonia, MHPCC 6 6 * 7 * @version $Revision: 1. 2$ $Name: not supported by cvs2svn $8 * @date $Date: 2004-09-2 1 22:30:19$7 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2004-09-23 18:30:57 $ 9 9 * 10 10 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 11 11 */ 12 12 13 #include <string.h> 14 13 15 #include "psImageConvolve.h" 14 16 #include "psImageFFT.h" 17 #include "psMatrixVectorArithmetic.h" 15 18 #include "psMemory.h" 16 19 #include "psLogMsg.h" … … 27 30 int numCols; 28 31 32 // following is explicitly spelled out in the SDRS as a requirement 29 33 if (yMin > yMax) { 30 34 int temp = yMin; … … 37 41 } 38 42 43 // following is explicitly spelled out in the SDRS as a requirement 39 44 if (xMin > xMax) { 40 45 int temp = xMin; … … 55 60 result->yMin = yMin; 56 61 result->yMax = yMax; 57 result-> p_data = psImageAlloc(numCols,numRows,PS_TYPE_F32);58 result->p_kernelRows = psAlloc(sizeof(ps F32*)*numRows);59 60 ps F32** kernelRows = result->p_kernelRows;61 ps F32** imageRows = result->p_data->data.F32;62 result->image = psImageAlloc(numCols,numRows,PS_TYPE_KERNEL); 63 result->p_kernelRows = psAlloc(sizeof(psKernelType*)*numRows); 64 65 psKernelType** kernelRows = result->p_kernelRows; 66 psKernelType** imageRows = result->image->data.PS_TYPE_KERNEL_DATA; 62 67 for (int i = 0; i < numRows; i++) { 63 68 kernelRows[i] = imageRows[i] - xMin; … … 73 78 { 74 79 if (ptr != NULL) { 75 psFree(ptr-> p_data);80 psFree(ptr->image); 76 81 psFree(ptr->p_kernelRows); 77 82 } 78 83 } 79 84 80 psKernel* psKernelGenerate(const psVector* xShifts, const psVector* yShifts) 85 psKernel* psKernelGenerate(const psVector* tShifts, 86 const psVector* xShifts, 87 const psVector* yShifts, 88 bool relative) 81 89 { 82 90 int x = 0; 83 91 int y = 0; 92 int t = 0; 93 int deltaT = 0; 84 94 int xMin = 0; 85 95 int xMax = 0; … … 87 97 int yMax = 0; 88 98 int length = 0; 89 ps F32 relativeTime = 1.0f;// fraction of total time for each shift clock99 psKernelType normalizeTime = 1.0; // fraction of total time for each shift clock 90 100 psKernel* result = NULL; 91 ps F32** kernel = NULL;101 psKernelType** kernel = NULL; 92 102 93 103 // got non-NULL vectors? … … 100 110 101 111 // types match? 102 if (xShifts->type.type != yShifts->type.type) { 112 if (xShifts->type.type != yShifts->type.type || 113 tShifts->type.type != xShifts->type.type) { 103 114 char* typeXStr; 104 115 char* typeYStr; 116 char* typeTStr; 105 117 PS_TYPE_NAME(typeXStr,xShifts->type.type); 106 118 PS_TYPE_NAME(typeYStr,yShifts->type.type); 119 PS_TYPE_NAME(typeTStr,tShifts->type.type); 107 120 psErrorMsg(PS_ERRORNAME_DOMAIN "psKernelGenerate", 108 121 PS_ERR_BAD_PARAMETER_TYPE, true, 109 122 PS_ERRORTEXT_psImageConvolve_SHIFT_TYPE_MISMATCH, 110 type XStr, typeYStr);123 typeTStr, typeXStr, typeYStr); 111 124 return NULL; 112 125 } 113 126 114 127 // determine the usable length of the shift vector 115 if (xShifts->n != yShifts->n) { 128 length = xShifts->n; 129 if (length != yShifts->n || 130 length != tShifts->n) { 116 131 psLogMsg(__func__,PS_LOG_WARN,"Shift vectors found to be different sizes."); 117 length = xShifts->n;118 132 if (yShifts->n < length) { 119 133 length = yShifts->n; 120 134 } 121 } else { 122 length = xShifts->n; 123 } 124 relativeTime = 1 / (1+length); // 1+length 'cause we count origin before shift 125 // e.g., 1 time unit at origin + a time unit for each shift clock 135 if (tShifts->n < length) { 136 length = tShifts->n; 137 } 138 } 126 139 127 140 #define KERNEL_GENERATE_CASE(TYPE) \ 128 141 case PS_TYPE_##TYPE: { \ 142 ps##TYPE *tShiftData = tShifts->data.TYPE; \ 129 143 ps##TYPE *xShiftData = xShifts->data.TYPE; \ 130 144 ps##TYPE *yShiftData = yShifts->data.TYPE; \ 131 145 for (int lcv = 0; lcv < length; lcv++) { \ 132 x += xShiftData[lcv]; \ 133 y += yShiftData[lcv]; \ 146 if (relative) { \ 147 x += xShiftData[lcv]; \ 148 y += yShiftData[lcv]; \ 149 } else { \ 150 x = xShiftData[lcv]; \ 151 y = yShiftData[lcv]; \ 152 } \ 134 153 if (x < xMin) { \ 135 154 xMin = x; \ … … 146 165 kernel = result->kernel; \ 147 166 \ 148 kernel[0][0]+=relativeTime; /* mark the original point as one exposure. */ \ 149 \ 150 x = 0; \ 151 y = 0; \ 152 for (int i = 0; i < length; i++) { \ 153 x += xShiftData[i]; \ 154 y += yShiftData[i]; \ 155 kernel[y][x]+=relativeTime; \ 167 x = xShiftData[0]; \ 168 y = yShiftData[0]; \ 169 t = tShiftData[0]; \ 170 normalizeTime = 1.0 / (psKernelType)(tShiftData[length-1]-t); \ 171 for (int i = 1; i < length; i++) { \ 172 deltaT = t; \ 173 if (relative) { \ 174 t += tShiftData[i]; \ 175 x += xShiftData[i]; \ 176 y += yShiftData[i]; \ 177 } else { \ 178 t = tShiftData[i]; \ 179 x = xShiftData[i]; \ 180 y = yShiftData[i]; \ 181 } \ 182 deltaT = t - deltaT; \ 183 \ 184 kernel[y][x] += deltaT * normalizeTime; \ 156 185 } \ 157 186 } … … 186 215 psImage* psImageConvolve(psImage* out, const psImage* in, const psKernel* kernel, bool direct) 187 216 { 188 189 190 return NULL; 217 if (in == NULL) { 218 psFree(out); 219 return NULL; 220 } 221 222 if (kernel == NULL) { 223 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 224 PS_ERR_BAD_PARAMETER_NULL, true, 225 PS_ERRORTEXT_psImageConvolve_KERNEL_NULL); 226 psFree(out); 227 return NULL; 228 } 229 int xMin = kernel->xMin; 230 int xMax = kernel->xMax; 231 int yMin = kernel->yMin; 232 int yMax = kernel->yMax; 233 psKernelType** kData = kernel->kernel; 234 235 // make the output image to the proper size and type 236 int numRows = in->numRows; 237 int numCols = in->numCols; 238 239 240 241 if (direct) { 242 // spatial convolution 243 244 #define SPATIAL_CONVOLVE_CASE(TYPE) \ 245 case PS_TYPE_##TYPE: { \ 246 ps##TYPE** inData = in->data.TYPE; \ 247 out = psImageRecycle(out, numCols, numRows, PS_TYPE_##TYPE); \ 248 for (int row=0;row<numRows;row++) { \ 249 ps##TYPE* outRow = out->data.TYPE[row]; \ 250 for (int col=0;col<numCols;col++) { \ 251 ps##TYPE pixel = 0.0; \ 252 for (int kRow = yMin; kRow < yMax; kRow++) { \ 253 if (row-kRow >= 0 && row-kRow < numRows) { \ 254 for (int kCol = xMin; kCol < xMax; kCol++) { \ 255 if (col-kCol >= 0 && col-kCol < numCols) { \ 256 pixel += kData[kRow][kCol] * inData[row-kRow][col-kCol]; \ 257 } \ 258 } \ 259 } \ 260 } \ 261 outRow[col] = pixel; \ 262 } \ 263 } \ 264 } \ 265 break; 266 267 switch (in->type.type) { 268 SPATIAL_CONVOLVE_CASE(U8) 269 SPATIAL_CONVOLVE_CASE(U16) 270 SPATIAL_CONVOLVE_CASE(U32) 271 SPATIAL_CONVOLVE_CASE(U64) 272 SPATIAL_CONVOLVE_CASE(S8) 273 SPATIAL_CONVOLVE_CASE(S16) 274 SPATIAL_CONVOLVE_CASE(S32) 275 SPATIAL_CONVOLVE_CASE(S64) 276 SPATIAL_CONVOLVE_CASE(F32) 277 SPATIAL_CONVOLVE_CASE(F64) 278 SPATIAL_CONVOLVE_CASE(C32) 279 SPATIAL_CONVOLVE_CASE(C64) 280 281 default: { 282 char* typeStr; 283 PS_TYPE_NAME(typeStr,in->type.type); 284 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 285 PS_ERR_BAD_PARAMETER_TYPE, true, 286 PS_ERRORTEXT_psImage_IMAGE_TYPE_UNSUPPORTED, 287 typeStr); 288 psFree(out); 289 return NULL; 290 291 } 292 } 293 294 295 } else { 296 // fourier convolution 297 int kRows = kernel->image->numRows; 298 int kCols = kernel->image->numCols; 299 int x0 = (numCols - kCols) / 2; 300 int y0 = (numRows - kRows) / 2; 301 psImage* paddedKernel; 302 303 // check to see if kernel is smaller, otherwise padding it up will fail. 304 if (x0 < 0 || y0 < 0) { 305 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 306 PS_ERR_BAD_PARAMETER_SIZE, true, 307 PS_ERRORTEXT_psImageConvolve_KERNEL_TOO_LARGE, 308 kernel->image->numCols,kernel->image->numRows, 309 numCols, numRows); 310 psFree(out); 311 return NULL; 312 } 313 314 // pad the kernel to the same size of image 315 paddedKernel = psImageAlloc(numCols,numRows,PS_TYPE_KERNEL); 316 memset(paddedKernel->data.V,0,sizeof(psKernelType)*numCols*numRows); // zeroize image 317 for (int row=0;row<kRows;row++) { 318 psKernelType* padRow = paddedKernel->data.PS_TYPE_KERNEL_DATA[row+y0]; 319 psKernelType* kernelRow = kernel->image->data.PS_TYPE_KERNEL_DATA[row]; 320 for (int col=0;col<kCols;col++) { 321 padRow[col+x0] = kernelRow[col]; 322 } 323 } 324 325 psImage* kernelFourier = psImageFFT(NULL, paddedKernel, PS_FFT_FORWARD); 326 if (kernelFourier == NULL) { 327 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 328 PS_ERR_UNKNOWN, false, 329 PS_ERRORTEXT_psImageConvolve_KERNEL_FFT_FAILED); 330 psFree(out); 331 return NULL; 332 } 333 334 335 psImage* inFourier = psImageFFT(NULL, in, PS_FFT_FORWARD); 336 if (inFourier == NULL) { 337 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 338 PS_ERR_UNKNOWN, false, 339 PS_ERRORTEXT_psImageConvolve_FFT_FAILED); 340 psFree(out); 341 return NULL; 342 } 343 344 // convolution in fourier domain is just a pixel-wise multiplication 345 psImage* outFourier = psImageAlloc(numCols,numRows,inFourier->type.type); 346 psBinaryOp(outFourier,inFourier,"*",kernelFourier); 347 348 psImage* complexOut = psImageFFT(NULL, outFourier, PS_FFT_REVERSE); 349 if (complexOut == NULL) { 350 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 351 PS_ERR_UNKNOWN, false, 352 PS_ERRORTEXT_psImageConvolve_FFT_FAILED); 353 psFree(out); 354 return NULL; 355 } 356 357 // since our image was real to start, the result is real 358 out = psImageReal(out,complexOut); 359 360 psFree(complexOut); 361 psFree(kernelFourier); 362 psFree(inFourier); 363 psFree(paddedKernel); 364 365 } 366 367 return out; 191 368 } -
trunk/psLib/src/image/psImageConvolve.h
r1653 r1863 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1. 1$ $Name: not supported by cvs2svn $10 * @date $Date: 2004-0 8-28 01:18:28$9 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2004-09-23 18:30:57 $ 11 11 * 12 12 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 13 13 */ 14 14 15 #ifndef PS_IMAGE_ FFT_H16 #define PS_IMAGE_ FFT_H15 #ifndef PS_IMAGE_CONVOLVE_H 16 #define PS_IMAGE_CONVOLVE_H 17 17 18 18 #include<stdbool.h> … … 20 20 #include "psImage.h" 21 21 #include "psVector.h" 22 #include "psType.h" 23 24 #define PS_TYPE_KERNEL PS_TYPE_F32 /**< the data member to use for kernel image */ 25 #define PS_TYPE_KERNEL_DATA F32 /**< the data member to use for kernel image */ 26 #define PS_TYPE_KERNEL_NAME "psF32" /**< the data type for kernel as a string */ 27 28 typedef psF32 psKernelType; 22 29 23 30 /** A convolution kernel */ 24 31 typedef struct 25 32 { 33 psImage* image; ///< Kernel data, in the form of an image 26 34 int xMin; ///< Most negative x index 27 35 int yMin; ///< Most negative y index 28 36 int xMax; ///< Most positive x index 29 37 int yMax; ///< Most positive y index 30 psF32** kernel; ///< Pointer to the kernel data 31 psF32** p_kernelRows; ///< Pointer to the rows of the kernel data 32 psImage* p_data; ///< Kernel data, in the form of an image 38 psKernelType** kernel; ///< Pointer to the kernel data 39 psKernelType** p_kernelRows; ///< Pointer to the rows of the kernel data; not intended for user use. 33 40 } 34 41 psKernel; … … 62 69 psKernel* psKernelAlloc( 63 70 int xMin, ///< Most negative x index 64 int xMax, ///< Most negative yindex65 int yMin, ///< Most positive xindex71 int xMax, ///< Most positive x index 72 int yMin, ///< Most negative y index 66 73 int yMax ///< Most positive y index 67 74 ); … … 84 91 */ 85 92 psKernel* psKernelGenerate( 86 const psVector* xShifts, ///< list of shifts relative to a reference point 87 const psVector* yShifts ///< list of shifts relative to a reference point 93 const psVector* tShifts, ///< list of time shifts 94 const psVector* xShifts, ///< list of x-axis shifts 95 const psVector* yShifts, ///< list of y-axis shifts 96 bool relative 88 97 ); 89 98 -
trunk/psLib/src/imageops/psImageConvolve.c
r1840 r1863 5 5 * @author Robert DeSonia, MHPCC 6 6 * 7 * @version $Revision: 1. 2$ $Name: not supported by cvs2svn $8 * @date $Date: 2004-09-2 1 22:30:19$7 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2004-09-23 18:30:57 $ 9 9 * 10 10 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 11 11 */ 12 12 13 #include <string.h> 14 13 15 #include "psImageConvolve.h" 14 16 #include "psImageFFT.h" 17 #include "psMatrixVectorArithmetic.h" 15 18 #include "psMemory.h" 16 19 #include "psLogMsg.h" … … 27 30 int numCols; 28 31 32 // following is explicitly spelled out in the SDRS as a requirement 29 33 if (yMin > yMax) { 30 34 int temp = yMin; … … 37 41 } 38 42 43 // following is explicitly spelled out in the SDRS as a requirement 39 44 if (xMin > xMax) { 40 45 int temp = xMin; … … 55 60 result->yMin = yMin; 56 61 result->yMax = yMax; 57 result-> p_data = psImageAlloc(numCols,numRows,PS_TYPE_F32);58 result->p_kernelRows = psAlloc(sizeof(ps F32*)*numRows);59 60 ps F32** kernelRows = result->p_kernelRows;61 ps F32** imageRows = result->p_data->data.F32;62 result->image = psImageAlloc(numCols,numRows,PS_TYPE_KERNEL); 63 result->p_kernelRows = psAlloc(sizeof(psKernelType*)*numRows); 64 65 psKernelType** kernelRows = result->p_kernelRows; 66 psKernelType** imageRows = result->image->data.PS_TYPE_KERNEL_DATA; 62 67 for (int i = 0; i < numRows; i++) { 63 68 kernelRows[i] = imageRows[i] - xMin; … … 73 78 { 74 79 if (ptr != NULL) { 75 psFree(ptr-> p_data);80 psFree(ptr->image); 76 81 psFree(ptr->p_kernelRows); 77 82 } 78 83 } 79 84 80 psKernel* psKernelGenerate(const psVector* xShifts, const psVector* yShifts) 85 psKernel* psKernelGenerate(const psVector* tShifts, 86 const psVector* xShifts, 87 const psVector* yShifts, 88 bool relative) 81 89 { 82 90 int x = 0; 83 91 int y = 0; 92 int t = 0; 93 int deltaT = 0; 84 94 int xMin = 0; 85 95 int xMax = 0; … … 87 97 int yMax = 0; 88 98 int length = 0; 89 ps F32 relativeTime = 1.0f;// fraction of total time for each shift clock99 psKernelType normalizeTime = 1.0; // fraction of total time for each shift clock 90 100 psKernel* result = NULL; 91 ps F32** kernel = NULL;101 psKernelType** kernel = NULL; 92 102 93 103 // got non-NULL vectors? … … 100 110 101 111 // types match? 102 if (xShifts->type.type != yShifts->type.type) { 112 if (xShifts->type.type != yShifts->type.type || 113 tShifts->type.type != xShifts->type.type) { 103 114 char* typeXStr; 104 115 char* typeYStr; 116 char* typeTStr; 105 117 PS_TYPE_NAME(typeXStr,xShifts->type.type); 106 118 PS_TYPE_NAME(typeYStr,yShifts->type.type); 119 PS_TYPE_NAME(typeTStr,tShifts->type.type); 107 120 psErrorMsg(PS_ERRORNAME_DOMAIN "psKernelGenerate", 108 121 PS_ERR_BAD_PARAMETER_TYPE, true, 109 122 PS_ERRORTEXT_psImageConvolve_SHIFT_TYPE_MISMATCH, 110 type XStr, typeYStr);123 typeTStr, typeXStr, typeYStr); 111 124 return NULL; 112 125 } 113 126 114 127 // determine the usable length of the shift vector 115 if (xShifts->n != yShifts->n) { 128 length = xShifts->n; 129 if (length != yShifts->n || 130 length != tShifts->n) { 116 131 psLogMsg(__func__,PS_LOG_WARN,"Shift vectors found to be different sizes."); 117 length = xShifts->n;118 132 if (yShifts->n < length) { 119 133 length = yShifts->n; 120 134 } 121 } else { 122 length = xShifts->n; 123 } 124 relativeTime = 1 / (1+length); // 1+length 'cause we count origin before shift 125 // e.g., 1 time unit at origin + a time unit for each shift clock 135 if (tShifts->n < length) { 136 length = tShifts->n; 137 } 138 } 126 139 127 140 #define KERNEL_GENERATE_CASE(TYPE) \ 128 141 case PS_TYPE_##TYPE: { \ 142 ps##TYPE *tShiftData = tShifts->data.TYPE; \ 129 143 ps##TYPE *xShiftData = xShifts->data.TYPE; \ 130 144 ps##TYPE *yShiftData = yShifts->data.TYPE; \ 131 145 for (int lcv = 0; lcv < length; lcv++) { \ 132 x += xShiftData[lcv]; \ 133 y += yShiftData[lcv]; \ 146 if (relative) { \ 147 x += xShiftData[lcv]; \ 148 y += yShiftData[lcv]; \ 149 } else { \ 150 x = xShiftData[lcv]; \ 151 y = yShiftData[lcv]; \ 152 } \ 134 153 if (x < xMin) { \ 135 154 xMin = x; \ … … 146 165 kernel = result->kernel; \ 147 166 \ 148 kernel[0][0]+=relativeTime; /* mark the original point as one exposure. */ \ 149 \ 150 x = 0; \ 151 y = 0; \ 152 for (int i = 0; i < length; i++) { \ 153 x += xShiftData[i]; \ 154 y += yShiftData[i]; \ 155 kernel[y][x]+=relativeTime; \ 167 x = xShiftData[0]; \ 168 y = yShiftData[0]; \ 169 t = tShiftData[0]; \ 170 normalizeTime = 1.0 / (psKernelType)(tShiftData[length-1]-t); \ 171 for (int i = 1; i < length; i++) { \ 172 deltaT = t; \ 173 if (relative) { \ 174 t += tShiftData[i]; \ 175 x += xShiftData[i]; \ 176 y += yShiftData[i]; \ 177 } else { \ 178 t = tShiftData[i]; \ 179 x = xShiftData[i]; \ 180 y = yShiftData[i]; \ 181 } \ 182 deltaT = t - deltaT; \ 183 \ 184 kernel[y][x] += deltaT * normalizeTime; \ 156 185 } \ 157 186 } … … 186 215 psImage* psImageConvolve(psImage* out, const psImage* in, const psKernel* kernel, bool direct) 187 216 { 188 189 190 return NULL; 217 if (in == NULL) { 218 psFree(out); 219 return NULL; 220 } 221 222 if (kernel == NULL) { 223 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 224 PS_ERR_BAD_PARAMETER_NULL, true, 225 PS_ERRORTEXT_psImageConvolve_KERNEL_NULL); 226 psFree(out); 227 return NULL; 228 } 229 int xMin = kernel->xMin; 230 int xMax = kernel->xMax; 231 int yMin = kernel->yMin; 232 int yMax = kernel->yMax; 233 psKernelType** kData = kernel->kernel; 234 235 // make the output image to the proper size and type 236 int numRows = in->numRows; 237 int numCols = in->numCols; 238 239 240 241 if (direct) { 242 // spatial convolution 243 244 #define SPATIAL_CONVOLVE_CASE(TYPE) \ 245 case PS_TYPE_##TYPE: { \ 246 ps##TYPE** inData = in->data.TYPE; \ 247 out = psImageRecycle(out, numCols, numRows, PS_TYPE_##TYPE); \ 248 for (int row=0;row<numRows;row++) { \ 249 ps##TYPE* outRow = out->data.TYPE[row]; \ 250 for (int col=0;col<numCols;col++) { \ 251 ps##TYPE pixel = 0.0; \ 252 for (int kRow = yMin; kRow < yMax; kRow++) { \ 253 if (row-kRow >= 0 && row-kRow < numRows) { \ 254 for (int kCol = xMin; kCol < xMax; kCol++) { \ 255 if (col-kCol >= 0 && col-kCol < numCols) { \ 256 pixel += kData[kRow][kCol] * inData[row-kRow][col-kCol]; \ 257 } \ 258 } \ 259 } \ 260 } \ 261 outRow[col] = pixel; \ 262 } \ 263 } \ 264 } \ 265 break; 266 267 switch (in->type.type) { 268 SPATIAL_CONVOLVE_CASE(U8) 269 SPATIAL_CONVOLVE_CASE(U16) 270 SPATIAL_CONVOLVE_CASE(U32) 271 SPATIAL_CONVOLVE_CASE(U64) 272 SPATIAL_CONVOLVE_CASE(S8) 273 SPATIAL_CONVOLVE_CASE(S16) 274 SPATIAL_CONVOLVE_CASE(S32) 275 SPATIAL_CONVOLVE_CASE(S64) 276 SPATIAL_CONVOLVE_CASE(F32) 277 SPATIAL_CONVOLVE_CASE(F64) 278 SPATIAL_CONVOLVE_CASE(C32) 279 SPATIAL_CONVOLVE_CASE(C64) 280 281 default: { 282 char* typeStr; 283 PS_TYPE_NAME(typeStr,in->type.type); 284 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 285 PS_ERR_BAD_PARAMETER_TYPE, true, 286 PS_ERRORTEXT_psImage_IMAGE_TYPE_UNSUPPORTED, 287 typeStr); 288 psFree(out); 289 return NULL; 290 291 } 292 } 293 294 295 } else { 296 // fourier convolution 297 int kRows = kernel->image->numRows; 298 int kCols = kernel->image->numCols; 299 int x0 = (numCols - kCols) / 2; 300 int y0 = (numRows - kRows) / 2; 301 psImage* paddedKernel; 302 303 // check to see if kernel is smaller, otherwise padding it up will fail. 304 if (x0 < 0 || y0 < 0) { 305 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 306 PS_ERR_BAD_PARAMETER_SIZE, true, 307 PS_ERRORTEXT_psImageConvolve_KERNEL_TOO_LARGE, 308 kernel->image->numCols,kernel->image->numRows, 309 numCols, numRows); 310 psFree(out); 311 return NULL; 312 } 313 314 // pad the kernel to the same size of image 315 paddedKernel = psImageAlloc(numCols,numRows,PS_TYPE_KERNEL); 316 memset(paddedKernel->data.V,0,sizeof(psKernelType)*numCols*numRows); // zeroize image 317 for (int row=0;row<kRows;row++) { 318 psKernelType* padRow = paddedKernel->data.PS_TYPE_KERNEL_DATA[row+y0]; 319 psKernelType* kernelRow = kernel->image->data.PS_TYPE_KERNEL_DATA[row]; 320 for (int col=0;col<kCols;col++) { 321 padRow[col+x0] = kernelRow[col]; 322 } 323 } 324 325 psImage* kernelFourier = psImageFFT(NULL, paddedKernel, PS_FFT_FORWARD); 326 if (kernelFourier == NULL) { 327 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 328 PS_ERR_UNKNOWN, false, 329 PS_ERRORTEXT_psImageConvolve_KERNEL_FFT_FAILED); 330 psFree(out); 331 return NULL; 332 } 333 334 335 psImage* inFourier = psImageFFT(NULL, in, PS_FFT_FORWARD); 336 if (inFourier == NULL) { 337 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 338 PS_ERR_UNKNOWN, false, 339 PS_ERRORTEXT_psImageConvolve_FFT_FAILED); 340 psFree(out); 341 return NULL; 342 } 343 344 // convolution in fourier domain is just a pixel-wise multiplication 345 psImage* outFourier = psImageAlloc(numCols,numRows,inFourier->type.type); 346 psBinaryOp(outFourier,inFourier,"*",kernelFourier); 347 348 psImage* complexOut = psImageFFT(NULL, outFourier, PS_FFT_REVERSE); 349 if (complexOut == NULL) { 350 psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve", 351 PS_ERR_UNKNOWN, false, 352 PS_ERRORTEXT_psImageConvolve_FFT_FAILED); 353 psFree(out); 354 return NULL; 355 } 356 357 // since our image was real to start, the result is real 358 out = psImageReal(out,complexOut); 359 360 psFree(complexOut); 361 psFree(kernelFourier); 362 psFree(inFourier); 363 psFree(paddedKernel); 364 365 } 366 367 return out; 191 368 } -
trunk/psLib/src/imageops/psImageConvolve.h
r1653 r1863 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1. 1$ $Name: not supported by cvs2svn $10 * @date $Date: 2004-0 8-28 01:18:28$9 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2004-09-23 18:30:57 $ 11 11 * 12 12 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 13 13 */ 14 14 15 #ifndef PS_IMAGE_ FFT_H16 #define PS_IMAGE_ FFT_H15 #ifndef PS_IMAGE_CONVOLVE_H 16 #define PS_IMAGE_CONVOLVE_H 17 17 18 18 #include<stdbool.h> … … 20 20 #include "psImage.h" 21 21 #include "psVector.h" 22 #include "psType.h" 23 24 #define PS_TYPE_KERNEL PS_TYPE_F32 /**< the data member to use for kernel image */ 25 #define PS_TYPE_KERNEL_DATA F32 /**< the data member to use for kernel image */ 26 #define PS_TYPE_KERNEL_NAME "psF32" /**< the data type for kernel as a string */ 27 28 typedef psF32 psKernelType; 22 29 23 30 /** A convolution kernel */ 24 31 typedef struct 25 32 { 33 psImage* image; ///< Kernel data, in the form of an image 26 34 int xMin; ///< Most negative x index 27 35 int yMin; ///< Most negative y index 28 36 int xMax; ///< Most positive x index 29 37 int yMax; ///< Most positive y index 30 psF32** kernel; ///< Pointer to the kernel data 31 psF32** p_kernelRows; ///< Pointer to the rows of the kernel data 32 psImage* p_data; ///< Kernel data, in the form of an image 38 psKernelType** kernel; ///< Pointer to the kernel data 39 psKernelType** p_kernelRows; ///< Pointer to the rows of the kernel data; not intended for user use. 33 40 } 34 41 psKernel; … … 62 69 psKernel* psKernelAlloc( 63 70 int xMin, ///< Most negative x index 64 int xMax, ///< Most negative yindex65 int yMin, ///< Most positive xindex71 int xMax, ///< Most positive x index 72 int yMin, ///< Most negative y index 66 73 int yMax ///< Most positive y index 67 74 ); … … 84 91 */ 85 92 psKernel* psKernelGenerate( 86 const psVector* xShifts, ///< list of shifts relative to a reference point 87 const psVector* yShifts ///< list of shifts relative to a reference point 93 const psVector* tShifts, ///< list of time shifts 94 const psVector* xShifts, ///< list of x-axis shifts 95 const psVector* yShifts, ///< list of y-axis shifts 96 bool relative 88 97 ); 89 98
Note:
See TracChangeset
for help on using the changeset viewer.
