1Hist_new_item = class 2 Menuaction "_New Histogram" "make a new histogram" { 3 action = class 4 _result { 5 _vislevel = 3; 6 7 d = Option "Depth" ["8 bit", "16 bit"] 0; 8 b = Scale "Black point" 0 100 0; 9 w = Scale "White point" 0 100 100; 10 11 sp = Scale "Shadow point" 0.1 0.3 0.2; 12 mp = Scale "Mid-tone point" 0.4 0.6 0.5; 13 hp = Scale "Highlight point" 0.7 0.9 0.8; 14 15 sa = Scale "Shadow adjust" (-15) 15 0; 16 ma = Scale "Mid-tone adjust" (-30) 30 0; 17 ha = Scale "Highlight adjust" (-15) 15 0; 18 19 _result 20 = tone_build fmt b w sp mp hp sa ma ha 21 { 22 fmt = [Image_format.UCHAR, Image_format.USHORT]?d; 23 } 24 } 25} 26 27Hist_new_from_matrix = Matrix_buildlut_item; 28 29Hist_from_image_item = class 30 Menuaction "Ta_g Image As Histogram" "set image Type field to Histogram" { 31 action x = hist_tag x; 32} 33 34#separator 35 36Hist_find_item = class 37 Menupullright "_Find Histogram" "find a histogram" { 38 Oned_item = class 39 Menuaction "_One Dimension" 40 "for a n-band image, make an n-band 1D histogram" { 41 action x = map_unary hist_find x; 42 } 43 44 Nd_item = class 45 Menuaction "_Many Dimensions" 46 "for a n-band image, make an n-dimensional histogram" { 47 action x = class 48 _result { 49 _vislevel = 3; 50 51 // default to something small-ish 52 bins = Expression "Number of bins in each dimension" 8; 53 54 _result 55 = map_unary process x 56 { 57 process in 58 = hist_find_nD bins in; 59 } 60 } 61 } 62} 63 64Hist_map_item = class 65 Menuaction "_Map Histogram" "map an image through a histogram" { 66 action x y 67 = map_binary map x y 68 { 69 map a b 70 = hist_map hist im 71 { 72 args = sortc (const is_hist) [a, b]; 73 im = args?0; 74 hist = args?1; 75 } 76 } 77} 78 79Hist_eq_item = Filter_enhance_item.Hist_equal_item; 80 81#separator 82 83Hist_cum_item = class 84 Menuaction "_Cumulativise Histogram" 85 "form cumulative histogram" { 86 action x = map_unary hist_cum x; 87} 88 89Hist_diff_item = class 90 Menuaction "_Differentiate Histogram" 91 "find point-to-point differences (inverse of Cumulativise)" { 92 action x = map_unary hist_diff x; 93} 94 95Hist_norm_item = class 96 Menuaction "N_ormalise Histogram" "normalise a histogram" { 97 action x = map_unary hist_norm x; 98} 99 100Hist_match_item = class 101 Menuaction "Ma_tch Histogram" 102 "find LUT which will match first histogram to second" { 103 action in ref = map_binary hist_match in ref; 104} 105 106Hist_zerox_item = class 107 Menuaction "_Zero Crossings" "find zero crossings" { 108 action x = class 109 _result { 110 _vislevel = 3; 111 112 edge = Option "Direction" [ 113 "Positive-going", 114 "Negative-going" 115 ] 0; 116 117 _result 118 = map_unary (zerox (if edge == 0 then -1 else 1)) x; 119 } 120} 121 122#separator 123 124Hist_profile_item = class 125 Menuaction "Find _Profile" 126 "search from image edges for non-zero pixels" { 127 action x = class 128 _result { 129 _vislevel = 3; 130 131 edge = Option "Search from" [ 132 "Top edge down", 133 "Left edge to right", 134 "Bottom edge up", 135 "Right edge to left" 136 ] 2; 137 138 _result 139 = map_unary profile x 140 { 141 profile image 142 = (Plot_histogram @ hist_tag) [ 143 profilemb 0 image.value, 144 profilemb 1 image.value, 145 profilemb 0 (fliptb image.value), 146 profilemb 1 (fliplr image.value) 147 ]?edge; 148 149 // im_profile only does 1 band images :-( 150 profilemb d = bandjoin @ map (converse im_profile d) @ bandsplit; 151 } 152 } 153} 154 155Hist_project_item = class 156 Menuaction "Find Pro_jections" 157 "find horizontal and vertical projections" { 158 action x = class { 159 _vislevel = 2; 160 161 _result = map_unary project x; 162 163 // extract the result ... could be a group 164 extr n 165 = Plot_histogram _result?n, is_list _result 166 = Group (map (Plot_histogram @ converse subscript n) _result.value); 167 168 horizontal = extr 0; 169 vertical = extr 1; 170 centre = (gravity horizontal, gravity vertical); 171 } 172} 173 174#separator 175 176Hist_graph_item = class 177 Menuaction "P_lot Slice" "plot a slice along a guide or arrow" { 178 action x = class 179 _value { 180 _vislevel = 3; 181 182 width = Scale "Width" 1 40 1; 183 displace = Scale "Horizontal displace" (-50) 50 0; 184 vdisplace = Scale "Vertical displace" (-50) 50 0; 185 186 _value 187 = map_unary graph x 188 { 189 graph arrow 190 = hist_tag area' 191 { 192 // the line as a polar vector 193 pv = polar (arrow.width, arrow.height); 194 a = im pv; 195 196 // smallest rotation that will make the line horizontal 197 a' 198 = 360 - a, a > 270 199 = 180 - a, a > 90 200 = -a; 201 202 im' = rotate a' arrow.image; 203 204 // look at the start and end of the arrow, pick the leftmost 205 p 206 = (arrow.left, arrow.top), arrow.left <= arrow.right 207 = (arrow.right, arrow.bottom); 208 209 // transform that point to im' space 210 p' = rectangular (polar p + (0, a')) + 211 (im'.xoffset, im'.yoffset); 212 213 // extract that area 214 area = extract_area 215 (re p' + displace.value) 216 (im p' - width.value / 2 + vdisplace.value) 217 (re pv) width.value 218 im'; 219 220 // squish vertically to get an average 221 area' = resize 1 (1 / width.value) Interpolate.BILINEAR area; 222 } 223 } 224 } 225} 226 227Extract_arrow_item = class 228 Menuaction "Extract _Arrow" "extract the area around an arrow" { 229 action x = class 230 _value { 231 _vislevel = 3; 232 233 width = Scale "Width" 1 40 1; 234 displace = Scale "Horizontal displace" (-50) 50 0; 235 vdisplace = Scale "Vertical displace" (-50) 50 0; 236 237 _value 238 = map_unary graph x 239 { 240 graph arrow 241 = area 242 { 243 // the line as a polar vector 244 pv = polar (arrow.width, arrow.height); 245 a = im pv; 246 247 // smallest rotation that will make the line horizontal 248 a' 249 = 360 - a, a > 270 250 = 180 - a, a > 90 251 = -a; 252 253 im' = rotate a' arrow.image; 254 255 // look at the start and end of the arrow, pick the leftmost 256 p 257 = (arrow.left, arrow.top), arrow.left <= arrow.right 258 = (arrow.right, arrow.bottom); 259 260 // transform that point to im' space 261 p' = rectangular (polar p + (0, a')) + 262 (im'.xoffset, im'.yoffset); 263 264 // extract that area 265 area = extract_area 266 (re p' + displace.value) 267 (im p' - width.value / 2 + vdisplace.value) 268 (re pv) width.value 269 im'; 270 } 271 } 272 } 273} 274 275Hist_plot_item = class 276 Menuaction "Plot _Object" 277 "plot an object as a bar, point or line graph" { 278 action x = class 279 _result { 280 _vislevel = 3; 281 282 format = Option_enum Plot_format.names "Format" "YYYY"; 283 style = Option_enum Plot_style.names "Style" "Line"; 284 285 auto = Toggle "Auto Range" true; 286 xmin = Expression "X range minimum" 0; 287 xmax = Expression "X range maximum" 1; 288 ymin = Expression "Y range minimum" 0; 289 ymax = Expression "Y range maximum" 1; 290 291 _result 292 = Plot options (image x) 293 { 294 options 295 = [["style", style.value], ["format", format.value]] ++ range; 296 range 297 = [], auto 298 = [["xmin", xmin.expr], ["xmax", xmax.expr], 299 ["ymin", ymin.expr], ["ymax", ymax.expr]]; 300 301 image x 302 = image (extract_arrow x), is_Arrow x 303 = get_image x, has_image x 304 = x2b im, b == 1 305 = im 306 { 307 im = get_image (to_image x); 308 w = get_width im; 309 h = get_height im; 310 b = get_bands im; 311 312 // matrix to image makes a 1-band mxn image 313 // we need to put columns into bands 314 x2b im 315 = bandjoin (map extract_col [0 .. w - 1]) 316 { 317 extract_col x = extract_area x 0 1 h im; 318 } 319 } 320 321 extract_arrow arrow 322 = extract_area (re p') (im p') (re pv) 1 im' 323 { 324 // the line as a polar vector 325 pv = polar (arrow.width, arrow.height); 326 a = im pv; 327 328 // smallest rotation that will make the line horizontal 329 a' 330 = 360 - a, a > 270 331 = 180 - a, a > 90 332 = -a; 333 334 im' = rotate a' arrow.image; 335 336 // look at the start and end of the arrow, pick the leftmost 337 p 338 = (arrow.left, arrow.top), arrow.left <= arrow.right 339 = (arrow.right, arrow.bottom); 340 341 // transform that point to im' space 342 p' = rectangular (polar p + (0, a')) + 343 (im'.xoffset, im'.yoffset); 344 } 345 } 346 } 347} 348