public GrayImage Filter1DSymmetric(GrayImage data, float[] filter, bool transpose) { GrayImage image = transpose ? new GrayImage(data.Height, data.Width) : new GrayImage(data.Width, data.Height); int num = 0; int num2 = transpose ? num : (num * image.Width); FilterJob job2 = new FilterJob(); job2.filter = filter; job2.data = data; job2.destPtr = num2; job2.result = image; job2.start = num; job2.end = data.Height / 2; FilterJob parameter = job2; ParameterizedThreadStart start = transpose ? new ParameterizedThreadStart(this.FilterPartSymmetricT) : new ParameterizedThreadStart(this.FilterPartSymmetric); Thread thread = new Thread(start); thread.Start(parameter); num = data.Height / 2; num2 = transpose ? num : (num * image.Width); parameter.start = num; parameter.destPtr = num2; parameter.end = data.Height; start(parameter); thread.Join(); return(image); }
/// <summary> /// Convolves an GrayImage with a 2D-symmetric operator. /// </summary> /// <param name="data">Data to be convolved with the operator</param> /// <param name="opUL">Lower-right quadrant of the operator.</param> /// <returns></returns> private GrayImage Conv2DSymm(GrayImage data, GrayImage opLR) { if (opLR.Width % 2 != 0 || opLR.Height % 2 != 0) { throw new ArgumentException("Operator must have an even number of rows and columns."); } int xPad = opLR.Width - 1; int yPad = opLR.Height - 1; GrayImage result = new GrayImage(data.Width - 2 * xPad, data.Height - 2 * yPad); for (int y = yPad; y < data.Height - yPad; y++) { for (int x = xPad; x < data.Width - xPad; x++) { // Center pixel float pixel = data[x, y] * opLR.Scan0[0]; // Vertical center for (int op_y = 1; op_y < opLR.Height; op_y++) { pixel += (data[x, y + op_y] + data[x, y - op_y]) * opLR[0, op_y]; } //Horizontal center for (int op_x = 1; op_x < opLR.Width; op_x++) { pixel += (data[x + op_x, y] + data[x - op_x, y]) * opLR[op_x, 0]; } //Quadrants int opIdx = 1; for (int op_y = 1; op_y < opLR.Height; op_y++) { int baseIdx1 = ((y + op_y) * data.Width) + x; int baseIdx2 = ((y - op_y) * data.Width) + x; // Loop unrolling can save 25% execution time here for (int op_x = 1; op_x < opLR.Width; op_x++) { pixel += (data.Scan0[baseIdx1 + op_x] + data.Scan0[baseIdx2 + op_x] + data.Scan0[baseIdx1 - op_x] + data.Scan0[baseIdx2 - op_x]) * opLR.Scan0[opIdx]; opIdx++; } opIdx++; // Skip 0th col on next row } result[x - xPad, y - yPad] = pixel; } // loop over data x } // loop over data y return(result); }
public GrayImage Conv2DSeparable(GrayImage data, float[] filter) { GrayImage pass1 = Filter1DSymmetric(data, filter, true); GrayImage result = Filter1DSymmetric(pass1, filter, true); return result; }
protected override void ApplyFilter() { // get source image size int width = _sourceData[0].GetLength(0), height = _sourceData[0].GetLength(1); int channels = _sourceData.Length; // Estimate a good filter size for the gaussian. // Note that gaussian isn't an ideal bandpass filter // so this is an experimentally determined quantity double std = (width / _newWidth) * 0.50; for (int i = 0; i < channels; i++) { GrayImage channel = new GrayImage(_sourceData[i]); channel = Convolution.Instance.GaussianConv(channel, std); _sourceData[i] = channel.ToByteArray2D(); } // number of pixels to shift in the original image double xStep = (double)width / _newWidth, yStep = (double)height / _newHeight; NNResize resizer = new NNResize(); _destinationData = resizer.Apply(_sourceData, _newWidth, _newHeight); }
/// <summary> /// Filters an GrayImage with a 1D symmetric filter along the X-axis. /// (This operation is multithreaded) /// </summary> /// <param name="data">GrayImage to be operated on</param> /// <param name="filter">Filter to use (center tap plus right-hand-side)</param> /// <param name="transpose">Transpose the result?</param> /// <returns>Transposed, filtered GrayImage.</returns> public GrayImage Filter1DSymmetric(GrayImage data, float[] filter, bool transpose) { GrayImage result = transpose ? new GrayImage(data.Height, data.Width) : new GrayImage(data.Width, data.Height); #if SILVERLIGHT || WIN int startY = 0; int destPtr = transpose ? startY : (startY * result.Width); FilterJob job = new FilterJob { filter = filter, data = data, destPtr = destPtr, result = result, start = startY, end = data.Height / 2 }; ParameterizedThreadStart del = transpose ? new ParameterizedThreadStart(FilterPartSymmetricT) : new ParameterizedThreadStart(FilterPartSymmetric); Thread worker = new Thread(del); worker.Start(job); startY = data.Height / 2; destPtr = transpose ? startY : (startY * result.Width); job.start = startY; job.destPtr = destPtr; job.end = data.Height; del((object)job); // Run the appropriate filter in this thread, too worker.Join(); #else FilterJob job = new FilterJob { filter = filter, data = data, destPtr = 0, result = result, start = 0, end = data.Height }; if (transpose) FilterPartSymmetricT(job); else FilterPartSymmetric(job); #endif return result; }
protected override void ApplyFilter() { // get source image size int width = _sourceData[0].GetLength(0), height = _sourceData[0].GetLength(1); int channels = _sourceData.Length; // Estimate a good filter size for the gaussian. // Note that gaussian isn't an ideal bandpass filter // so this is an experimentally determined quantity double std = (width / _newWidth) * 0.50; for(int i = 0; i < channels; i++) { GrayImage channel = new GrayImage(_sourceData[i]); channel = Convolution.Instance.GaussianConv(channel, std); _sourceData[i] = channel.ToByteArray2D(); } // number of pixels to shift in the original image double xStep = (double)width / _newWidth, yStep = (double)height / _newHeight; NNResize resizer = new NNResize(); _destinationData = resizer.Apply(_sourceData, _newWidth, _newHeight); }
public GrayImage Conv2DSeparable(GrayImage data, float[] filter) { GrayImage pass1 = Filter1DSymmetric(data, filter, true); GrayImage result = Filter1DSymmetric(pass1, filter, true); return(result); }
public void FilterPartSymmetric(object filterJob) { FilterJob filterJob2 = (FilterJob)filterJob; GrayImage data = filterJob2.data; float[] scan = data.Scan0; float[] filter = filterJob2.filter; float[] scan2 = filterJob2.result.Scan0; int num = filter.Length - 1; int destPtr = filterJob2.destPtr; for (int i = filterJob2.start; i < filterJob2.end; i++) { int num2 = i * data.Width; for (int j = 0; j < num; j++) { float num3 = scan[num2] * filter[0]; for (int k = 1; k < j + 1; k++) { num3 += (scan[num2 + k] + scan[num2 - k]) * filter[k]; } for (int l = j + 1; l < filter.Length; l++) { num3 += (scan[num2 + l] + scan[num2 + l]) * filter[l]; } scan2[destPtr++] = num3; num2++; } for (int m = num; m < data.Width - num; m++) { float num4 = scan[num2] * filter[0]; for (int n = 1; n < filter.Length; n++) { num4 += (scan[num2 + n] + scan[num2 - n]) * filter[n]; } scan2[destPtr++] = num4; num2++; } for (int num5 = data.Width - num; num5 < data.Width; num5++) { float num6 = scan[num2] * filter[0]; for (int num7 = 0; num7 < data.Width - num5; num7++) { num6 += (scan[num2 + num7] + scan[num2 - num7]) * filter[num7]; } for (int num8 = data.Width - num5; num8 < filter.Length; num8++) { num6 += (scan[num2 + num8] + scan[num2 - num8]) * filter[num8]; } scan2[destPtr++] = num6; num2++; } } }
/// <summary> /// Vanilla 2D convolution. Not optimized. /// </summary> /// <param name="data"></param> /// <param name="op"></param> /// <returns></returns> public GrayImage Conv2D(GrayImage data, GrayImage op) { GrayImage result = new GrayImage(data.Width, data.Height); if (op.Width % 2 == 0 || op.Height % 2 == 0) { throw new ArgumentException("Operator must have an odd number of rows and columns."); } int x_offset = op.Width / 2; int y_offset = op.Height / 2; for (int y = 0; y < data.Height; y++) { for (int x = 0; x < data.Width; x++) { float pixel = 0; float wt = 0; for (int op_y = 0; op_y < op.Height; op_y++) { int d_y = y - y_offset + op_y; if (d_y < 0 || d_y >= data.Height) { continue; } for (int op_x = 0; op_x < op.Width; op_x++) { int d_x = x - x_offset + op_x; if (d_x < 0 || d_x >= data.Width) { continue; } float op_val = op[op_x, op_y]; /* Perform actual convolution */ wt += Math.Abs(op_val); pixel += data[d_x, d_y] * op_val; } } result[x, y] = pixel / wt; } // loop over data x } // loop over data y return(result); }
protected override void ApplyFilter() { int length = base._sourceData[0].GetLength(0); int num2 = base._sourceData[0].GetLength(1); int num3 = base._sourceData.Length; double std = (length / base._newWidth) * 0.5; for (int i = 0; i < num3; i++) { GrayImage data = new GrayImage(base._sourceData[i]); base._sourceData[i] = Convolution.Instance.GaussianConv(data, std).ToByteArray2D(); } double num6 = ((double) length) / ((double) base._newWidth); double num7 = ((double) num2) / ((double) base._newHeight); base._destinationData = new NNResize().Apply(base._sourceData, base._newWidth, base._newHeight); }
protected override void ApplyFilter() { int length = base._sourceData[0].GetLength(0); int num2 = base._sourceData[0].GetLength(1); int num3 = base._sourceData.Length; double std = (length / base._newWidth) * 0.5; for (int i = 0; i < num3; i++) { GrayImage data = new GrayImage(base._sourceData[i]); base._sourceData[i] = Convolution.Instance.GaussianConv(data, std).ToByteArray2D(); } double num6 = ((double)length) / ((double)base._newWidth); double num7 = ((double)num2) / ((double)base._newHeight); base._destinationData = new NNResize().Apply(base._sourceData, base._newWidth, base._newHeight); }
public GrayImage Conv2DSymmetric(GrayImage data, GrayImage opLR) { int num = opLR.Width - 1; int num2 = opLR.Height - 1; GrayImage image = new GrayImage(data.Width + (2 * num), data.Height + (2 * num2)); int index = 0; for (int i = 0; i < data.Height; i++) { int num5 = ((i + num2) * (data.Width + (2 * num))) + num; for (int j = 0; j < data.Width; j++) { image.Scan0[num5 + j] = data.Scan0[index]; index++; } } return(this.Conv2DSymm(image, opLR)); }
public GrayImage Conv2DSymmetric(GrayImage data, GrayImage opLR) { int num = opLR.Width - 1; int num2 = opLR.Height - 1; GrayImage grayImage = new GrayImage(data.Width + 2 * num, data.Height + 2 * num2); int num3 = 0; for (int i = 0; i < data.Height; i++) { int num4 = (i + num2) * (data.Width + 2 * num) + num; for (int j = 0; j < data.Width; j++) { grayImage.Scan0[num4 + j] = data.Scan0[num3]; num3++; } } return(Conv2DSymm(grayImage, opLR)); }
private GrayImage Conv2DSymm(GrayImage data, GrayImage opLR) { if (((opLR.Width % 2) != 0) || ((opLR.Height % 2) != 0)) { throw new ArgumentException("Operator must have an even number of rows and columns."); } int num = opLR.Width - 1; int num2 = opLR.Height - 1; GrayImage image = new GrayImage(data.Width - (2 * num), data.Height - (2 * num2)); for (int i = num2; i < (data.Height - num2); i++) { for (int j = num; j < (data.Width - num); j++) { float num5 = data[j, i] * opLR.Scan0[0]; int num6 = 1; while (num6 < opLR.Height) { num5 += (data[j, i + num6] + data[j, i - num6]) * opLR[0, num6]; num6++; } int num7 = 1; while (num7 < opLR.Width) { num5 += (data[j + num7, i] + data[j - num7, i]) * opLR[num7, 0]; num7++; } int index = 1; for (num6 = 1; num6 < opLR.Height; num6++) { int num9 = ((i + num6) * data.Width) + j; int num10 = ((i - num6) * data.Width) + j; for (num7 = 1; num7 < opLR.Width; num7++) { num5 += (((data.Scan0[num9 + num7] + data.Scan0[num10 + num7]) + data.Scan0[num9 - num7]) + data.Scan0[num10 - num7]) * opLR.Scan0[index]; index++; } index++; } image[j - num, i - num2] = num5; } } return(image); }
/// <summary> /// Filters an GrayImage with a 1D symmetric filter along the X-axis. /// (This operation is multithreaded) /// </summary> /// <param name="data">GrayImage to be operated on</param> /// <param name="filter">Filter to use (center tap plus right-hand-side)</param> /// <param name="transpose">Transpose the result?</param> /// <returns>Transposed, filtered GrayImage.</returns> public GrayImage Filter1DSymmetric(GrayImage data, float[] filter, bool transpose) { GrayImage result = transpose ? new GrayImage(data.Height, data.Width) : new GrayImage(data.Width, data.Height); int startY = 0; int destPtr = transpose ? startY : (startY * result.Width); FilterJob job = new FilterJob { filter = filter, data = data, destPtr = destPtr, result = result, start = startY, end = data.Height / 2 }; ParameterizedThreadStart del = transpose ? new ParameterizedThreadStart(FilterPartSymmetricT) : new ParameterizedThreadStart(FilterPartSymmetric); Thread worker = new Thread(del); worker.Start(job); startY = data.Height / 2; destPtr = transpose ? startY : (startY * result.Width); job.start = startY; job.destPtr = destPtr; job.end = data.Height; del((object)job); // Run the appropriate filter in this thread, too worker.Join(); return(result); }
private GrayImage Conv2DSymm(GrayImage data, GrayImage opLR) { if (((opLR.Width % 2) != 0) || ((opLR.Height % 2) != 0)) { throw new ArgumentException("Operator must have an even number of rows and columns."); } int num = opLR.Width - 1; int num2 = opLR.Height - 1; GrayImage image = new GrayImage(data.Width - (2 * num), data.Height - (2 * num2)); for (int i = num2; i < (data.Height - num2); i++) { for (int j = num; j < (data.Width - num); j++) { float num5 = data[j, i] * opLR.Scan0[0]; int num6 = 1; while (num6 < opLR.Height) { num5 += (data[j, i + num6] + data[j, i - num6]) * opLR[0, num6]; num6++; } int num7 = 1; while (num7 < opLR.Width) { num5 += (data[j + num7, i] + data[j - num7, i]) * opLR[num7, 0]; num7++; } int index = 1; for (num6 = 1; num6 < opLR.Height; num6++) { int num9 = ((i + num6) * data.Width) + j; int num10 = ((i - num6) * data.Width) + j; for (num7 = 1; num7 < opLR.Width; num7++) { num5 += (((data.Scan0[num9 + num7] + data.Scan0[num10 + num7]) + data.Scan0[num9 - num7]) + data.Scan0[num10 - num7]) * opLR.Scan0[index]; index++; } index++; } image[j - num, i - num2] = num5; } } return image; }
/// <summary> /// Vanilla 2D convolution. Not optimized. /// </summary> /// <param name="data"></param> /// <param name="op"></param> /// <returns></returns> public GrayImage Conv2D(GrayImage data, GrayImage op) { GrayImage result = new GrayImage(data.Width, data.Height); if (op.Width % 2 == 0 || op.Height % 2 == 0) throw new ArgumentException("Operator must have an odd number of rows and columns."); int x_offset = op.Width / 2; int y_offset = op.Height / 2; for (int y = 0; y < data.Height; y++) { for (int x = 0; x < data.Width; x++) { float pixel = 0; float wt = 0; for (int op_y = 0; op_y < op.Height; op_y++) { int d_y = y - y_offset + op_y; if (d_y < 0 || d_y >= data.Height) continue; for (int op_x = 0; op_x < op.Width; op_x++) { int d_x = x - x_offset + op_x; if (d_x < 0 || d_x >= data.Width) continue; float op_val = op[op_x, op_y]; /* Perform actual convolution */ wt += Math.Abs(op_val); pixel += data[d_x, d_y] * op_val; } } result[x, y] = pixel / wt; } // loop over data x } // loop over data y return result; }
public GrayImage Conv2DSymmetric(GrayImage data, GrayImage opLR) { int xPad = opLR.Width - 1; int yPad = opLR.Height - 1; GrayImage padded = new GrayImage(data.Width + 2 * xPad, data.Height + 2 * yPad); int dataIdx = 0; for (int y = 0; y < data.Height; y++) { int rowStart = (y + yPad) * (data.Width + 2 * xPad) + xPad; for (int x = 0; x < data.Width; x++) { padded.Scan0[rowStart + x] = data.Scan0[dataIdx]; dataIdx++; } } return Conv2DSymm(padded, opLR); }
public GrayImage Conv2DSymmetric(GrayImage data, GrayImage opLR) { int xPad = opLR.Width - 1; int yPad = opLR.Height - 1; GrayImage padded = new GrayImage(data.Width + 2 * xPad, data.Height + 2 * yPad); int dataIdx = 0; for (int y = 0; y < data.Height; y++) { int rowStart = (y + yPad) * (data.Width + 2 * xPad) + xPad; for (int x = 0; x < data.Width; x++) { padded.Scan0[rowStart + x] = data.Scan0[dataIdx]; dataIdx++; } } return(Conv2DSymm(padded, opLR)); }
public GrayImage Conv2D(GrayImage data, GrayImage op) { GrayImage grayImage = new GrayImage(data.Width, data.Height); if (op.Width % 2 == 0 || op.Height % 2 == 0) { throw new ArgumentException("Operator must have an odd number of rows and columns."); } int num = op.Width / 2; int num2 = op.Height / 2; for (int i = 0; i < data.Height; i++) { for (int j = 0; j < data.Width; j++) { float num3 = 0f; float num4 = 0f; for (int k = 0; k < op.Height; k++) { int num5 = i - num2 + k; if (num5 < 0 || num5 >= data.Height) { continue; } for (int l = 0; l < op.Width; l++) { int num6 = j - num + l; if (num6 >= 0 && num6 < data.Width) { float num7 = op[l, k]; num4 += Math.Abs(num7); num3 += data[num6, num5] * num7; } } } grayImage[j, i] = num3 / num4; } } return(grayImage); }
public GrayImage Conv2DSymm(GrayImage data, GrayImage opLR) { if (opLR.Width % 2 != 0 || opLR.Height % 2 != 0) { throw new ArgumentException("Operator must have an even number of rows and columns."); } int num = opLR.Width - 1; int num2 = opLR.Height - 1; GrayImage grayImage = new GrayImage(data.Width - 2 * num, data.Height - 2 * num2); for (int i = num2; i < data.Height - num2; i++) { for (int j = num; j < data.Width - num; j++) { float num3 = data[j, i] * opLR.Scan0[0]; for (int k = 1; k < opLR.Height; k++) { num3 += (data[j, i + k] + data[j, i - k]) * opLR[0, k]; } for (int l = 1; l < opLR.Width; l++) { num3 += (data[j + l, i] + data[j - l, i]) * opLR[l, 0]; } int num4 = 1; for (int m = 1; m < opLR.Height; m++) { int num5 = (i + m) * data.Width + j; int num6 = (i - m) * data.Width + j; for (int n = 1; n < opLR.Width; n++) { num3 += (data.Scan0[num5 + n] + data.Scan0[num6 + n] + data.Scan0[num5 - n] + data.Scan0[num6 - n]) * opLR.Scan0[num4]; num4++; } num4++; } grayImage[j - num, i - num2] = num3; } } return(grayImage); }
public GrayImage Conv2D(GrayImage data, GrayImage op) { GrayImage image = new GrayImage(data.Width, data.Height); if (((op.Width % 2) == 0) || ((op.Height % 2) == 0)) { throw new ArgumentException("Operator must have an odd number of rows and columns."); } int num = op.Width / 2; int num2 = op.Height / 2; for (int i = 0; i < data.Height; i++) { for (int j = 0; j < data.Width; j++) { float num5 = 0f; float num6 = 0f; for (int k = 0; k < op.Height; k++) { int num8 = (i - num2) + k; if ((num8 >= 0) && (num8 < data.Height)) { for (int m = 0; m < op.Width; m++) { int num10 = (j - num) + m; if ((num10 >= 0) && (num10 < data.Width)) { float num11 = op[m, k]; num6 += Math.Abs(num11); num5 += data[num10, num8] * num11; } } } } image[j, i] = num5 / num6; } } return(image); }
public GrayImage Filter1DSymmetric(GrayImage data, float[] filter, bool transpose) { GrayImage result = transpose ? new GrayImage(data.Height, data.Width) : new GrayImage(data.Width, data.Height); FilterJob filterJob = default(FilterJob); filterJob.filter = filter; filterJob.data = data; filterJob.destPtr = 0; filterJob.result = result; filterJob.start = 0; filterJob.end = data.Height; FilterJob filterJob2 = filterJob; if (transpose) { FilterPartSymmetricT(filterJob2); } else { FilterPartSymmetric(filterJob2); } return(result); }
public GrayImage Conv2D(GrayImage data, GrayImage op) { GrayImage image = new GrayImage(data.Width, data.Height); if (((op.Width % 2) == 0) || ((op.Height % 2) == 0)) { throw new ArgumentException("Operator must have an odd number of rows and columns."); } int num = op.Width / 2; int num2 = op.Height / 2; for (int i = 0; i < data.Height; i++) { for (int j = 0; j < data.Width; j++) { float num5 = 0f; float num6 = 0f; for (int k = 0; k < op.Height; k++) { int num8 = (i - num2) + k; if ((num8 >= 0) && (num8 < data.Height)) { for (int m = 0; m < op.Width; m++) { int num10 = (j - num) + m; if ((num10 >= 0) && (num10 < data.Width)) { float num11 = op[m, k]; num6 += Math.Abs(num11); num5 += data[num10, num8] * num11; } } } } image[j, i] = num5 / num6; } } return image; }
public GrayImage GaussianConv(GrayImage data, double std) { float[] filter = GaussianFilter(std); return Conv2DSeparable(data, filter); }
public GrayImage Conv2DSeparable(GrayImage data, float[] filter) { GrayImage data2 = Filter1DSymmetric(data, filter, transpose: true); return(Filter1DSymmetric(data2, filter, transpose: true)); }
public GrayImage Filter1DSymmetric(GrayImage data, float[] filter, bool transpose) { GrayImage image = transpose ? new GrayImage(data.Height, data.Width) : new GrayImage(data.Width, data.Height); int num = 0; int num2 = transpose ? num : (num * image.Width); FilterJob job2 = new FilterJob(); job2.filter = filter; job2.data = data; job2.destPtr = num2; job2.result = image; job2.start = num; job2.end = data.Height / 2; FilterJob parameter = job2; ParameterizedThreadStart start = transpose ? new ParameterizedThreadStart(this.FilterPartSymmetricT) : new ParameterizedThreadStart(this.FilterPartSymmetric); Thread thread = new Thread(start); thread.Start(parameter); num = data.Height / 2; num2 = transpose ? num : (num * image.Width); parameter.start = num; parameter.destPtr = num2; parameter.end = data.Height; start(parameter); thread.Join(); return image; }
public GrayImage GaussianConv(GrayImage data, double std) { float[] filter = GaussianFilter(std); return(Conv2DSeparable(data, filter)); }
public GrayImage Conv2DSymmetric(GrayImage data, GrayImage opLR) { int num = opLR.Width - 1; int num2 = opLR.Height - 1; GrayImage image = new GrayImage(data.Width + (2 * num), data.Height + (2 * num2)); int index = 0; for (int i = 0; i < data.Height; i++) { int num5 = ((i + num2) * (data.Width + (2 * num))) + num; for (int j = 0; j < data.Width; j++) { image.Scan0[num5 + j] = data.Scan0[index]; index++; } } return this.Conv2DSymm(image, opLR); }
public GrayImage Conv2DSeparable(GrayImage data, float[] filter) { GrayImage image = this.Filter1DSymmetric(data, filter, true); return this.Filter1DSymmetric(image, filter, true); }
/// <summary> /// Convolves an GrayImage with a 1D filter along the X-axis. /// </summary> /// <param name="filterJob">Filter operation details</param> private void FilterPartSymmetric(object filterJob) { FilterJob fj = (FilterJob)filterJob; GrayImage data = fj.data; float[] srcData = data.Scan0; float[] filter = fj.filter; GrayImage result = fj.result; float[] resData = result.Scan0; int pad = filter.Length - 1; int destPtr = fj.destPtr; #region Filter (no transpose) for (int y = fj.start; y < fj.end; y++) { int rowStart = y * data.Width; int ptr = fj.dataPtr + rowStart; // Left checked region for (int x = 0; x < pad; x++) { float pixel = srcData[ptr] * filter[0]; // Part of the filter that fits within the GrayImage for (int i = 1; i < x + 1; i++) { pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i]; } // Part of the filter that falls off the left side for (int i = x + 1; i < filter.Length; i++) { pixel += (srcData[ptr + i] + srcData[ptr + i]) * filter[i]; } resData[destPtr++] = pixel; ptr++; } // Unchecked region for (int x = pad; x < data.Width - pad; x++) { float pixel = srcData[ptr] * filter[0]; for (int i = 1; i < filter.Length; i++) { pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i]; } resData[destPtr++] = pixel; ptr++; } // Right checked region for (int x = data.Width - pad; x < data.Width; x++) { float pixel = srcData[ptr] * filter[0]; // Part of the filter that fits within the GrayImage for (int i = 0; i < (data.Width - x); i++) { pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i]; } // Part of the filter that falls off the right side for (int i = (data.Width - x); i < filter.Length; i++) { pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i]; } resData[destPtr++] = pixel; ptr++; } } #endregion }
public GrayImage Conv2DSeparable(GrayImage data, float[] filter) { GrayImage image = this.Filter1DSymmetric(data, filter, true); return(this.Filter1DSymmetric(image, filter, true)); }
private void FilterPartSymmetricT(object filterJob) { FilterJob job = (FilterJob)filterJob; GrayImage data = job.data; float[] numArray = data.Scan0; float[] filter = job.filter; GrayImage result = job.result; int num = filter.Length - 1; for (int i = job.start; i < job.end; i++) { float num6; int num7; int num3 = i * data.Width; int index = num3; int num5 = 0; while (num5 < num) { num6 = numArray[index] * filter[0]; num7 = 1; while (num7 < (num5 + 1)) { num6 += (numArray[index + num7] + numArray[index - num7]) * filter[num7]; num7++; } num7 = num5 + 1; while (num7 < filter.Length) { num6 += (numArray[index + num7] + numArray[index + num7]) * filter[num7]; num7++; } result[i, num5] = num6; index++; num5++; } num5 = num; while (num5 < (data.Width - num)) { num6 = numArray[index] * filter[0]; num7 = 1; while (num7 < filter.Length) { num6 += (numArray[index + num7] + numArray[index - num7]) * filter[num7]; num7++; } result[i, num5] = num6; index++; num5++; } for (num5 = data.Width - num; num5 < data.Width; num5++) { num6 = numArray[index] * filter[0]; num7 = 1; while (num7 < (data.Width - num5)) { num6 += (numArray[index + num7] + numArray[index - num7]) * filter[num7]; num7++; } for (num7 = data.Width - num5; num7 < filter.Length; num7++) { num6 += (numArray[index - num7] + numArray[index - num7]) * filter[num7]; } result[i, num5] = num6; index++; } } }
private void FilterPartSymmetric(object filterJob) { FilterJob job = (FilterJob)filterJob; GrayImage data = job.data; float[] numArray = data.Scan0; float[] filter = job.filter; float[] numArray3 = job.result.Scan0; int num = filter.Length - 1; int destPtr = job.destPtr; for (int i = job.start; i < job.end; i++) { float num7; int num8; int num4 = i * data.Width; int index = job.dataPtr + num4; int num6 = 0; while (num6 < num) { num7 = numArray[index] * filter[0]; num8 = 1; while (num8 < (num6 + 1)) { num7 += (numArray[index + num8] + numArray[index - num8]) * filter[num8]; num8++; } num8 = num6 + 1; while (num8 < filter.Length) { num7 += (numArray[index + num8] + numArray[index + num8]) * filter[num8]; num8++; } numArray3[destPtr++] = num7; index++; num6++; } num6 = num; while (num6 < (data.Width - num)) { num7 = numArray[index] * filter[0]; num8 = 1; while (num8 < filter.Length) { num7 += (numArray[index + num8] + numArray[index - num8]) * filter[num8]; num8++; } numArray3[destPtr++] = num7; index++; num6++; } for (num6 = data.Width - num; num6 < data.Width; num6++) { num7 = numArray[index] * filter[0]; num8 = 0; while (num8 < (data.Width - num6)) { num7 += (numArray[index + num8] + numArray[index - num8]) * filter[num8]; num8++; } for (num8 = data.Width - num6; num8 < filter.Length; num8++) { num7 += (numArray[index + num8] + numArray[index - num8]) * filter[num8]; } numArray3[destPtr++] = num7; index++; } } }
/// <summary> /// Convolves an GrayImage with a 2D-symmetric operator. /// </summary> /// <param name="data">Data to be convolved with the operator</param> /// <param name="opUL">Lower-right quadrant of the operator.</param> /// <returns></returns> private GrayImage Conv2DSymm(GrayImage data, GrayImage opLR) { if (opLR.Width % 2 != 0 || opLR.Height % 2 != 0) throw new ArgumentException("Operator must have an even number of rows and columns."); int xPad = opLR.Width - 1; int yPad = opLR.Height - 1; GrayImage result = new GrayImage(data.Width - 2 * xPad, data.Height - 2 * yPad); for (int y = yPad; y < data.Height - yPad; y++) { for (int x = xPad; x < data.Width - xPad; x++) { // Center pixel float pixel = data[x, y] * opLR.Scan0[0]; // Vertical center for (int op_y = 1; op_y < opLR.Height; op_y++) pixel += (data[x, y + op_y] + data[x, y - op_y]) * opLR[0, op_y]; //Horizontal center for (int op_x = 1; op_x < opLR.Width; op_x++) pixel += (data[x + op_x, y] + data[x - op_x, y]) * opLR[op_x, 0]; //Quadrants int opIdx = 1; for (int op_y = 1; op_y < opLR.Height; op_y++) { int baseIdx1 = ((y + op_y) * data.Width) + x; int baseIdx2 = ((y - op_y) * data.Width) + x; // Loop unrolling can save 25% execution time here for (int op_x = 1; op_x < opLR.Width; op_x++) { pixel += (data.Scan0[baseIdx1 + op_x] + data.Scan0[baseIdx2 + op_x] + data.Scan0[baseIdx1 - op_x] + data.Scan0[baseIdx2 - op_x]) * opLR.Scan0[opIdx]; opIdx++; } opIdx++; // Skip 0th col on next row } result[x - xPad, y - yPad] = pixel; } // loop over data x } // loop over data y return result; }