Hi all,
Does anyone know if there is a way to filter out noises on a square waveform (as shown in figure below), without changing the maximum and minimum values of the amplitude? The max of the peaks varies, so does the min and the frequency. I wrote a script to identify each max/min by the second derivative being zero. But it's identifying the little peaks of noise as well. Please see the following for my code. Thanks, Danju macro "Resolution Evaluation Tool - Cf00T5f20r" { if (selectionType==0) exit("Draw a line on resolution target"); run("Clear Results"); profile = getProfile(); for (i=0; i<profile.length; i++) { setResult("Value", i, profile[i]); } updateResults; Plot.create("Profile", "X", "Value", profile); //build diffs diff = newArray(profile.length-1); for (i=0; i<diff.length; i++) { diff[i] = profile[i+1] - profile[i]; } //find inflection points topbot = newArray(diff.length); j = 0; flag = sgn(diff[0]); for (i=1; i<diff.length; ) { stop = 0; while (i < diff.length && stop == 0) { if (sgn(diff[i]) == flag) i = i + 1; else stop = 1; } topbot[j] = profile[i]; j = j + 1; flag = -flag; i = i + 1; } Array.print(topbot); Array.getStatistics(topbot, min, max); print ("max = ", max); //delete fake max/min maxmin = newArray(topbot.length); l = 0; for (j=1; j<=topbot.length; ) { stop2 = 0; while (j < topbot.length && stop2 == 0) { if (abs(topbot[j-1] - topbot[j]) < 0.1*max) j = j + 1; else stop2 = 1; } maxmin[l] = topbot[j-1]; l = l + 1; j = j + 1; } Array.print(maxmin); //compute ratio ratios = newArray(l-1); avg_ratio = 0; for (k=0; k<ratios.length; k++) { ratios[k] = maxmin[k+1]/maxmin[k]; if (ratios[k] > 1) ratios[k] = 1 / ratios[k]; avg_ratio = avg_ratio + ratios[k]; } avg_ratio = avg_ratio / ratios.length; if (avg_ratio > 0.74) print ("Imin/Imax ratio =", avg_ratio, "> 0.74, Fail!"); else print ("Imin/Imax ratio =", avg_ratio, "< 0.74, Pass:)"); function sgn(x) { if (x >= 0) return 1; else return -1; } -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Try integrating and checking the slope. If the square wave has a true flat top, its integral will have a slope ~1.0. The interval with an average 1.0 slope will identify the flat spot in the square wave, and you can then average the points in that interval to find the max.
On Oct 25, 2012, at 12:55 PM, Danju Men wrote: > Hi all, > > > > Does anyone know if there is a way to filter out noises on a square waveform > (as shown in figure below), without changing the maximum and minimum values > of the amplitude? > > The max of the peaks varies, so does the min and the frequency. > > I wrote a script to identify each max/min by the second derivative being > zero. But it's identifying the little peaks of noise as well. > > Please see the following for my code. > > > > Thanks, > > Danju > > > > > > macro "Resolution Evaluation Tool - Cf00T5f20r" { > > if (selectionType==0) > > exit("Draw a line on resolution target"); > > > > run("Clear Results"); > > profile = getProfile(); > > > > for (i=0; i<profile.length; i++) { > > setResult("Value", i, profile[i]); > > } > > updateResults; > > Plot.create("Profile", "X", "Value", profile); > > > > //build diffs > > diff = newArray(profile.length-1); > > for (i=0; i<diff.length; i++) { > > diff[i] = profile[i+1] - profile[i]; > > } > > > > //find inflection points > > topbot = newArray(diff.length); > > j = 0; > > flag = sgn(diff[0]); > > > > for (i=1; i<diff.length; ) { > > stop = 0; > > while (i < diff.length && stop == 0) { > > if (sgn(diff[i]) == flag) > > i = i + 1; > > else > > stop = 1; > > } > > topbot[j] = profile[i]; > > j = j + 1; > > flag = -flag; > > i = i + 1; > > } > > Array.print(topbot); > > Array.getStatistics(topbot, min, max); > > print ("max = ", max); > > > > //delete fake max/min > > maxmin = newArray(topbot.length); > > l = 0; > > > > for (j=1; j<=topbot.length; ) { > > stop2 = 0; > > while (j < topbot.length && stop2 == 0) { > > if (abs(topbot[j-1] - topbot[j]) < 0.1*max) > > j = j + 1; > > else > > stop2 = 1; > > } > > maxmin[l] = topbot[j-1]; > > l = l + 1; > > j = j + 1; > > } > > Array.print(maxmin); > > > > //compute ratio > > ratios = newArray(l-1); > > avg_ratio = 0; > > > > for (k=0; k<ratios.length; k++) { > > ratios[k] = maxmin[k+1]/maxmin[k]; > > if (ratios[k] > 1) > > ratios[k] = 1 / ratios[k]; > > avg_ratio = avg_ratio + ratios[k]; > > } > > > > avg_ratio = avg_ratio / ratios.length; > > if (avg_ratio > 0.74) > > print ("Imin/Imax ratio =", avg_ratio, "> 0.74, Fail!"); > > else > > print ("Imin/Imax ratio =", avg_ratio, "< 0.74, Pass:)"); > > > > function sgn(x) { > > if (x >= 0) > > return 1; > > else > > return -1; > > } > > > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Danju Men
Hi Danju,
two thoughts on this: (1) use an edge-preserving filter on the image, such as thresholded blur http://imagejdocu.tudor.lu/doku.php?id=plugin:filter:thresholded_blur:start (2) use a line width larger than 1 (double-click the line tool) to reduce noise Michael ________________________________________________________________ On Oct 25, 2012, at 18:55, Danju Men wrote: > Hi all, > > > > Does anyone know if there is a way to filter out noises on a square waveform > (as shown in figure below), without changing the maximum and minimum values > of the amplitude? > > The max of the peaks varies, so does the min and the frequency. > > I wrote a script to identify each max/min by the second derivative being > zero. But it's identifying the little peaks of noise as well. > > Please see the following for my code. > > > > Thanks, > > Danju > > > > > > macro "Resolution Evaluation Tool - Cf00T5f20r" { > > if (selectionType==0) > > exit("Draw a line on resolution target"); > > > > run("Clear Results"); > > profile = getProfile(); > > > > for (i=0; i<profile.length; i++) { > > setResult("Value", i, profile[i]); > > } > > updateResults; > > Plot.create("Profile", "X", "Value", profile); > > > > //build diffs > > diff = newArray(profile.length-1); > > for (i=0; i<diff.length; i++) { > > diff[i] = profile[i+1] - profile[i]; > > } > > > > //find inflection points > > topbot = newArray(diff.length); > > j = 0; > > flag = sgn(diff[0]); > > > > for (i=1; i<diff.length; ) { > > stop = 0; > > while (i < diff.length && stop == 0) { > > if (sgn(diff[i]) == flag) > > i = i + 1; > > else > > stop = 1; > > } > > topbot[j] = profile[i]; > > j = j + 1; > > flag = -flag; > > i = i + 1; > > } > > Array.print(topbot); > > Array.getStatistics(topbot, min, max); > > print ("max = ", max); > > > > //delete fake max/min > > maxmin = newArray(topbot.length); > > l = 0; > > > > for (j=1; j<=topbot.length; ) { > > stop2 = 0; > > while (j < topbot.length && stop2 == 0) { > > if (abs(topbot[j-1] - topbot[j]) < 0.1*max) > > j = j + 1; > > else > > stop2 = 1; > > } > > maxmin[l] = topbot[j-1]; > > l = l + 1; > > j = j + 1; > > } > > Array.print(maxmin); > > > > //compute ratio > > ratios = newArray(l-1); > > avg_ratio = 0; > > > > for (k=0; k<ratios.length; k++) { > > ratios[k] = maxmin[k+1]/maxmin[k]; > > if (ratios[k] > 1) > > ratios[k] = 1 / ratios[k]; > > avg_ratio = avg_ratio + ratios[k]; > > } > > > > avg_ratio = avg_ratio / ratios.length; > > if (avg_ratio > 0.74) > > print ("Imin/Imax ratio =", avg_ratio, "> 0.74, Fail!"); > > else > > print ("Imin/Imax ratio =", avg_ratio, "< 0.74, Pass:)"); > > > > function sgn(x) { > > if (x >= 0) > > return 1; > > else > > return -1; > > } > > > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Danju Men
Danju - This looks like stochastic data sampled discretely in time. It appears that you want to estimate the max and min (or maybe the max minus the min) in these various peaks and valleys. You can Fourier Transform (segments of) the signal, filter out the highest-frequency elements, and inverse transform to generate the filtered signal. Alternatively, and nearly equivalently, you can run a filter across the data - try a Gaussian filter first, experiment with widths (depends on your sampling frequency). The filter will bias your estimates slightly (low for max, high for min), so you may want to find the best-estimate maximum or minimum from the filtered curve, but take the value of the unfiltered curve at that point.
- Jim On Oct 25, 2012, at 12:55 PM, Danju Men wrote: > Hi all, > > > > Does anyone know if there is a way to filter out noises on a square waveform > (as shown in figure below), without changing the maximum and minimum values > of the amplitude? > > The max of the peaks varies, so does the min and the frequency. > > I wrote a script to identify each max/min by the second derivative being > zero. But it's identifying the little peaks of noise as well. > > Please see the following for my code. > > > > Thanks, > > Danju > > > > > > macro "Resolution Evaluation Tool - Cf00T5f20r" { > > if (selectionType==0) > > exit("Draw a line on resolution target"); > > > > run("Clear Results"); > > profile = getProfile(); > > > > for (i=0; i<profile.length; i++) { > > setResult("Value", i, profile[i]); > > } > > updateResults; > > Plot.create("Profile", "X", "Value", profile); > > > > //build diffs > > diff = newArray(profile.length-1); > > for (i=0; i<diff.length; i++) { > > diff[i] = profile[i+1] - profile[i]; > > } > > > > //find inflection points > > topbot = newArray(diff.length); > > j = 0; > > flag = sgn(diff[0]); > > > > for (i=1; i<diff.length; ) { > > stop = 0; > > while (i < diff.length && stop == 0) { > > if (sgn(diff[i]) == flag) > > i = i + 1; > > else > > stop = 1; > > } > > topbot[j] = profile[i]; > > j = j + 1; > > flag = -flag; > > i = i + 1; > > } > > Array.print(topbot); > > Array.getStatistics(topbot, min, max); > > print ("max = ", max); > > > > //delete fake max/min > > maxmin = newArray(topbot.length); > > l = 0; > > > > for (j=1; j<=topbot.length; ) { > > stop2 = 0; > > while (j < topbot.length && stop2 == 0) { > > if (abs(topbot[j-1] - topbot[j]) < 0.1*max) > > j = j + 1; > > else > > stop2 = 1; > > } > > maxmin[l] = topbot[j-1]; > > l = l + 1; > > j = j + 1; > > } > > Array.print(maxmin); > > > > //compute ratio > > ratios = newArray(l-1); > > avg_ratio = 0; > > > > for (k=0; k<ratios.length; k++) { > > ratios[k] = maxmin[k+1]/maxmin[k]; > > if (ratios[k] > 1) > > ratios[k] = 1 / ratios[k]; > > avg_ratio = avg_ratio + ratios[k]; > > } > > > > avg_ratio = avg_ratio / ratios.length; > > if (avg_ratio > 0.74) > > print ("Imin/Imax ratio =", avg_ratio, "> 0.74, Fail!"); > > else > > print ("Imin/Imax ratio =", avg_ratio, "< 0.74, Pass:)"); > > > > function sgn(x) { > > if (x >= 0) > > return 1; > > else > > return -1; > > } > > > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Dear list members,
I am happy to announce two 1 day ImageJ workshops, introduction and macro writing, on Monday 17 and Tuesday 18 December 2012. Please visit the website: http://www.le.ac.uk/biochem/microscopy/ImageJ2012.html for more information . Best wishes Kees Dr Ir K.R. Straatman Senior Experimental Officer Centre for Core Biotechnology Services University of Leicester, UK Postal address: Department of Biochemistry Henry Wellcome Building University of Leicester Lancaster Rd. Leicester LE1 9HN UK tel.: + 44 (0)116 229 7085/252 2263 fax: + 44 (0)116 229 7031 -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Danju Men
Danju,
In your "//delete fake max/min" section, you do not keep track of the max or min values for each region of the square waveform. When you detect a large change in consecutive topbot values (i.e., > 0.1*max), you record the topbot[ j-1 ] value, even if it was not the max (or min) value of that region. Try the modified macro pasted at the bottom. It may not handle the last one or two points in the profile the way you want (how many points do you need on one region of the square wave before you include it in your test?). The basic idea is simply to proceed along the profile tracking the maximum (if above 128) or minimum (if below 128), record the value to the minmax array any time the next profile value switches above or below 128, and reset the values for tracking regional max or min. You might want to try a threshold equal to the mean of your profile values rather than 128 (which works for my testing on the Blobs image). -----Original Message----- From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of Danju Men Sent: Thursday, October 25, 2012 11:56 AM To: [hidden email] Subject: How to filter out noises on a square waveform Hi all, Does anyone know if there is a way to filter out noises on a square waveform (as shown in figure below), without changing the maximum and minimum values of the amplitude? The max of the peaks varies, so does the min and the frequency. I wrote a script to identify each max/min by the second derivative being zero. But it's identifying the little peaks of noise as well. Please see the following for my code. Thanks, Danju //macro "Resolution Evaluation Tool - Cf00T5f20r" { if (selectionType==0) exit("Draw a line on resolution target"); run("Clear Results"); profile = getProfile(); for (i=0; i<profile.length; i++) { setResult("Value", i, profile[i]); } updateResults; Plot.create("Profile", "X", "Value", profile); Array.getStatistics(profile, min, max); //print ("max= ", max); //Array.print(profile); copy = newArray(profile.length); for ( i=0; i< copy.length; i++) { copy[i] = profile[i]; } Array.print(copy); maxmin = newArray(copy.length); l = 0; j = 0; maxtrack=0; mintrack=255; while ( j < maxmin.length-1 ) { //print("J= ", j); // 0-72 here when results are 1-73 if (copy[j] > 128) maxtrack = maxOf(maxtrack, copy[j]); if (copy[j] <= 128) mintrack = minOf(mintrack, copy[j]); if (copy[j+1] <=128 && mintrack==255 ) record = 1; else if (copy[j+1] >128 && maxtrack==0 ) record = 1; else if (j == maxmin.length-2) record = 1; else record = 0; if (record==1) { // Record max or min, then reset maxtrack, mintrack if (maxtrack >0) maxmin[l] = maxtrack; if (mintrack <255) maxmin[l] = mintrack; maxtrack=0; mintrack=255; l = l + 1; } j = j+1; } Array.print(maxmin); //compute ratio ratios = newArray(l-1); avg_ratio = 0; for (k=0; k<ratios.length; k++) { ratios[k] = maxmin[k+1]/maxmin[k]; if (ratios[k] > 1) ratios[k] = 1 / ratios[k]; avg_ratio = avg_ratio + ratios[k]; } avg_ratio = avg_ratio / ratios.length; if (avg_ratio > 0.74) print ("Imin/Imax ratio =", avg_ratio, "> 0.74, Fail!"); else print ("Imin/Imax ratio =", avg_ratio, "< 0.74, Pass:)"); -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Free forum by Nabble | Edit this page |