Hist_new_item = class Menuaction "_New Histogram" "make a new histogram" { action = class _result { _vislevel = 3; d = Option "Depth" ["8 bit", "16 bit"] 0; b = Scale "Black point" 0 100 0; w = Scale "White point" 0 100 100; sp = Scale "Shadow point" 0.1 0.3 0.2; mp = Scale "Mid-tone point" 0.4 0.6 0.5; hp = Scale "Highlight point" 0.7 0.9 0.8; sa = Scale "Shadow adjust" (-15) 15 0; ma = Scale "Mid-tone adjust" (-30) 30 0; ha = Scale "Highlight adjust" (-15) 15 0; _result = tone_build fmt b w sp mp hp sa ma ha { fmt = [Image_format.UCHAR, Image_format.USHORT]?d; } } } Hist_new_from_matrix = Matrix_buildlut_item; Hist_from_image_item = class Menuaction "Ta_g Image As Histogram" "set image Type field to Histogram" { action x = hist_tag x; } #separator Hist_find_item = class Menupullright "_Find Histogram" "find a histogram" { Oned_item = class Menuaction "_One Dimension" "for a n-band image, make an n-band 1D histogram" { action x = map_unary hist_find x; } Nd_item = class Menuaction "_Many Dimensions" "for a n-band image, make an n-dimensional histogram" { action x = class _result { _vislevel = 3; // default to something small-ish bins = Expression "Number of bins in each dimension" 8; _result = map_unary process x { process in = hist_find_nD bins in; } } } } Hist_map_item = class Menuaction "_Map Histogram" "map an image through a histogram" { action x y = map_binary map x y { map a b = hist_map hist im { args = sortc (const is_hist) [a, b]; im = args?0; hist = args?1; } } } Hist_eq_item = Filter_enhance_item.Hist_equal_item; #separator Hist_cum_item = class Menuaction "_Cumulativise Histogram" "form cumulative histogram" { action x = map_unary hist_cum x; } Hist_diff_item = class Menuaction "_Differentiate Histogram" "find point-to-point differences (inverse of Cumulativise)" { action x = map_unary hist_diff x; } Hist_norm_item = class Menuaction "N_ormalise Histogram" "normalise a histogram" { action x = map_unary hist_norm x; } Hist_match_item = class Menuaction "Ma_tch Histogram" "find LUT which will match first histogram to second" { action in ref = map_binary hist_match in ref; } Hist_zerox_item = class Menuaction "_Zero Crossings" "find zero crossings" { action x = class _result { _vislevel = 3; edge = Option "Direction" [ "Positive-going", "Negative-going" ] 0; _result = map_unary (zerox (if edge == 0 then -1 else 1)) x; } } #separator Hist_profile_item = class Menuaction "Find _Profile" "search from image edges for non-zero pixels" { action x = class _result { _vislevel = 3; edge = Option "Search from" [ "Top edge down", "Left edge to right", "Bottom edge up", "Right edge to left" ] 2; _result = map_unary profile x { profile image = (Plot_histogram @ hist_tag) [ profilemb 0 image.value, profilemb 1 image.value, profilemb 0 (fliptb image.value), profilemb 1 (fliplr image.value) ]?edge; // im_profile only does 1 band images :-( profilemb d = bandjoin @ map (converse im_profile d) @ bandsplit; } } } Hist_project_item = class Menuaction "Find Pro_jections" "find horizontal and vertical projections" { action x = class { _vislevel = 2; _result = map_unary project x; // extract the result ... could be a group extr n = Plot_histogram _result?n, is_list _result = Group (map (Plot_histogram @ converse subscript n) _result.value); horizontal = extr 0; vertical = extr 1; centre = (gravity horizontal, gravity vertical); } } #separator Hist_graph_item = class Menuaction "P_lot Slice" "plot a slice along a guide or arrow" { action x = class _value { _vislevel = 3; width = Scale "Width" 1 40 1; displace = Scale "Horizontal displace" (-50) 50 0; vdisplace = Scale "Vertical displace" (-50) 50 0; _value = map_unary graph x { graph arrow = hist_tag area' { // the line as a polar vector pv = polar (arrow.width, arrow.height); a = im pv; // smallest rotation that will make the line horizontal a' = 360 - a, a > 270 = 180 - a, a > 90 = -a; im' = rotate a' arrow.image; // look at the start and end of the arrow, pick the leftmost p = (arrow.left, arrow.top), arrow.left <= arrow.right = (arrow.right, arrow.bottom); // transform that point to im' space p' = rectangular (polar p + (0, a')) + (im'.xoffset, im'.yoffset); // extract that area area = extract_area (re p' + displace.value) (im p' - width.value / 2 + vdisplace.value) (re pv) width.value im'; // squish vertically to get an average area' = resize 1 (1 / width.value) Interpolate.BILINEAR area; } } } } Extract_arrow_item = class Menuaction "Extract _Arrow" "extract the area around an arrow" { action x = class _value { _vislevel = 3; width = Scale "Width" 1 40 1; displace = Scale "Horizontal displace" (-50) 50 0; vdisplace = Scale "Vertical displace" (-50) 50 0; _value = map_unary graph x { graph arrow = area { // the line as a polar vector pv = polar (arrow.width, arrow.height); a = im pv; // smallest rotation that will make the line horizontal a' = 360 - a, a > 270 = 180 - a, a > 90 = -a; im' = rotate a' arrow.image; // look at the start and end of the arrow, pick the leftmost p = (arrow.left, arrow.top), arrow.left <= arrow.right = (arrow.right, arrow.bottom); // transform that point to im' space p' = rectangular (polar p + (0, a')) + (im'.xoffset, im'.yoffset); // extract that area area = extract_area (re p' + displace.value) (im p' - width.value / 2 + vdisplace.value) (re pv) width.value im'; } } } } Hist_plot_item = class Menuaction "Plot _Object" "plot an object as a bar, point or line graph" { action x = class _result { _vislevel = 3; format = Option_enum Plot_format.names "Format" "YYYY"; style = Option_enum Plot_style.names "Style" "Line"; auto = Toggle "Auto Range" true; xmin = Expression "X range minimum" 0; xmax = Expression "X range maximum" 1; ymin = Expression "Y range minimum" 0; ymax = Expression "Y range maximum" 1; _result = Plot options (image x) { options = [["style", style.value], ["format", format.value]] ++ range; range = [], auto = [["xmin", xmin.expr], ["xmax", xmax.expr], ["ymin", ymin.expr], ["ymax", ymax.expr]]; image x = image (extract_arrow x), is_Arrow x = get_image x, has_image x = x2b im, b == 1 = im { im = get_image (to_image x); w = get_width im; h = get_height im; b = get_bands im; // matrix to image makes a 1-band mxn image // we need to put columns into bands x2b im = bandjoin (map extract_col [0 .. w - 1]) { extract_col x = extract_area x 0 1 h im; } } extract_arrow arrow = extract_area (re p') (im p') (re pv) 1 im' { // the line as a polar vector pv = polar (arrow.width, arrow.height); a = im pv; // smallest rotation that will make the line horizontal a' = 360 - a, a > 270 = 180 - a, a > 90 = -a; im' = rotate a' arrow.image; // look at the start and end of the arrow, pick the leftmost p = (arrow.left, arrow.top), arrow.left <= arrow.right = (arrow.right, arrow.bottom); // transform that point to im' space p' = rectangular (polar p + (0, a')) + (im'.xoffset, im'.yoffset); } } } }