diff --git a/examples/workflows/alexmac/config.json b/examples/workflows/alexmac/config.json new file mode 100644 index 0000000000000000000000000000000000000000..52a126c8c803052abfcec272f40f1a4194cbd290 --- /dev/null +++ b/examples/workflows/alexmac/config.json @@ -0,0 +1,27 @@ +{ + "version": "1.0", + "installdir": "/home/aknecht/stash/walia/ih/ih/build/scripts-2.7/", + "profile": { + "pegasus": { + "style": "condor" + }, + "condor": { + "universe": "vanilla", + "requirements": "OSGVO_OS_STRING == \"RHEL 6\" && HAS_FILE_usr_lib64_libstdc___so_6 && CVMFS_oasis_opensciencegrid_org_REVISION >= 3590", + "+WantsStashCache": "True" + } + }, + "osg": { + "tarball": "/home/aknecht/stash/walia/ih/ih/dist/ih-1.0.tar.gz", + "ssh": "/home/aknecht/.ssh/workflow" + }, + "cluster": 50, + "maxwalltime": { + "stats": 300, + "images": 3 + }, + "notify": { + "email": "avi@kurtknecht.com", + "pegasus_home": "/usr/share/pegasus/" + } +} diff --git a/examples/workflows/alexmac/crawl.json b/examples/workflows/alexmac/crawl.json new file mode 100644 index 0000000000000000000000000000000000000000..635c0e464525080bbeb94f349e1edcf986b553c4 --- /dev/null +++ b/examples/workflows/alexmac/crawl.json @@ -0,0 +1,42 @@ +{ + "path": "/home/aknecht/stash/9-22-15_lemnatec_images/alexmac/%experiment%_%id%-%genotype%_%date%_%null%_%null%/%stype%_%view%_%angle%/0_0_0.png", + "base": "/home/aknecht/stash/9-22-15_lemnatec_images/alexmac/", + "filetype": ".png", + "order": ["experiment", "id", "genotype", "date", "imgname", "imtype", "path"], + "translations": { + "imtype": { + "fluo_sv": "fluosv", + "vis_tv": "rgbtv", + "vis_sv": "rgbsv" + } + }, + "data": { + "experiment": { + "type": "value", + "value": "%experiment%" + }, + "id": { + "type": "value", + "value": "%id%" + }, + "genotype": { + "type": "value", + "value": "%genotype%" + }, + "date": { + "type": "date", + "value": "%date%", + "format": "Y-m-d" + }, + "imtype": { + "type": "value", + "translate": "true", + "value": "%stype%_%view%", + "case": "lower" + }, + "imgname": { + "type": "value", + "value": "%stype%_%view%_%angle%" + } + } +} diff --git a/examples/workflows/alexmac/fluosv_edge.json b/examples/workflows/alexmac/fluosv_edge.json new file mode 100644 index 0000000000000000000000000000000000000000..03f1ef17653f8d73828ff7dfb161610b18ad1ab9 --- /dev/null +++ b/examples/workflows/alexmac/fluosv_edge.json @@ -0,0 +1,6 @@ +{ + "ystart": 590, + "yend": 1190, + "xstart": 219, + "xend": 799 +} diff --git a/examples/workflows/alexmac/imgproc.json b/examples/workflows/alexmac/imgproc.json new file mode 100644 index 0000000000000000000000000000000000000000..d73feb4e9a2bf1535609d838ab3dd5609b6d7aeb --- /dev/null +++ b/examples/workflows/alexmac/imgproc.json @@ -0,0 +1,348 @@ +{ + "workflows": { + + "fluosv": [ + { + "name": "gray", + "executable": "ih-convert-color", + "inputs": ["base"], + "outputs": ["grayscale"], + "arguments": { + "--intype": "bgr", + "--outtype": "gray" + } + }, + { + "name": "blur", + "executable": "ih-gaussian-blur", + "inputs": ["grayscale"], + "outputs": ["blurred"], + "arguments": { + "--kwidth": 5, + "--kheight": 5 + }, + "depends": ["gray"] + }, + { + "name": "thresh", + "executable": "ih-threshold", + "inputs": ["blurred"], + "outputs": ["masked"], + "arguments": { + "--thresh": 0, + "--max": 255, + "--type": "otsu" + }, + "depends": ["blur"] + }, + { + "name": "reconstitute", + "executable": "ih-bitwise-and", + "inputs": ["masked", "base"], + "outputs": ["recolor"], + "arguments": {}, + "depends": ["thresh"] + }, + { + "name": "crop", + "executable": "ih-crop", + "inputs": ["recolor", "/home/aknecht/stash/walia/ih/workflows/alexmac/input/fluosv_edge.json"], + "outputs": ["edged"], + "arguments": {}, + "depends": ["reconstitute"] + }, + { + "name": "cut", + "executable": "ih-contour-cut", + "inputs": ["edged", "edged"], + "outputs": ["final"], + "arguments": { + "--resize": "", + "--basemin": 50 + }, + "depends": ["crop"] + } + ], + + + + "rgbtv": [ + { + "name": "blur", + "executable": "ih-gaussian-blur", + "inputs": ["base"], + "outputs": ["blurred"], + "arguments": { + "--kwidth": 13, + "--kheight": 13 + } + }, + { + "name": "sharpen", + "executable": "ih-add-weighted", + "inputs": ["base", "blurred"], + "outputs": ["sharpened"], + "arguments": { + "--weight1": 1.5, + "--weight2": -0.5 + }, + "depends": ["blur"] + }, + { + "name": "crop", + "executable": "ih-crop", + "inputs": ["sharpened", "/home/aknecht/stash/walia/ih/workflows/alexmac/input/rgbtv_edge.json"], + "outputs": ["edged"], + "arguments": {}, + "depends": ["sharpen"] + }, + { + "name": "cfilter1", + "executable": "ih-color-filter", + "inputs": ["edged"], + "outputs": ["cf1"], + "arguments": { + "--logic": "((r > b) or ((g > r) and ((g - b) > 10)))" + }, + "depends": ["crop"] + }, + { + "name": "bgr_lab", + "executable": "ih-convert-color", + "inputs": ["cf1"], + "outputs": ["lab_spectrum"], + "arguments": { + "--intype": "bgr", + "--outtype": "lab" + }, + "depends": ["cfilter1"] + }, + { + "name": "labfilter1", + "executable": "ih-color-filter", + "inputs": ["lab_spectrum"], + "outputs": ["lf1"], + "arguments": { + "--logic": "((r - g) > 5)" + }, + "depends": ["bgr_lab"] + }, + { + "name": "labfilter2", + "executable": "ih-color-filter", + "inputs": ["lf1"], + "outputs": ["lf2"], + "arguments": { + "--logic": "((r > b) and (g > b))" + }, + "depends": ["labfilter1"] + }, + { + "name": "mask", + "executable": "ih-mask", + "inputs": ["lf2"], + "outputs": ["masked"], + "arguments": {}, + "depends": ["labfilter2"] + }, + { + "name": "reconstitute", + "executable": "ih-bitwise-and", + "inputs": ["masked", "base"], + "outputs": ["recolor"], + "arguments": {}, + "depends": ["mask"] + }, + { + "name": "cfilter2", + "executable": "ih-color-filter", + "inputs": ["recolor"], + "outputs": ["cf2"], + "arguments": { + "--logic": "(((r - g) < ((i * i) / 4000)) or (((r - g) > (40 * (1 - (i / 765)))) and ((r - b) > (60 * (1 - (i / 765))))))" + }, + "depends": ["reconstitute"] + }, + { + "name": "erode", + "executable": "ih-morphology", + "inputs": ["cf2"], + "outputs": ["morph_erode"], + "arguments": { + "--ktype": "ellipse", + "--kwidth": 3, + "--kheight": 3, + "--morphType": "erode" + }, + "depends": ["cfilter2"] + }, + { + "name": "contour_chop", + "executable": "ih-contour-chop", + "inputs": ["morph_erode", "morph_erode"], + "outputs": ["chop"], + "arguments": { + "--basemin": 100 + }, + "depends": ["erode"] + }, + { + "name": "mask2", + "executable": "ih-mask", + "inputs": ["chop"], + "outputs": ["mask2"], + "arguments": {}, + "depends": ["contour_chop"] + }, + { + "name": "dilate", + "executable": "ih-morphology", + "inputs": ["mask2"], + "outputs": ["morph_dilate"], + "arguments": { + "--ktype": "ellipse", + "--kwidth": 3, + "--kheight": 3, + "--morphType": "dilate" + }, + "depends": ["mask2"] + }, + { + "name": "reconstitute2", + "executable": "ih-bitwise-and", + "inputs": ["morph_dilate", "base"], + "outputs": ["recolor2"], + "arguments": {}, + "depends": ["dilate"] + }, + { + "name": "cut", + "executable": "ih-contour-cut", + "inputs": ["recolor2", "recolor2"], + "outputs": ["final"], + "arguments": { + "--basemin": 100, + "--resize": "" + }, + "depends": ["reconstitute2"] + } + ], + "rgbsv": [ + { + "name": "gray", + "executable": "ih-convert-color", + "inputs": ["base"], + "outputs": ["grayscale"], + "arguments": { + "--intype": "bgr", + "--outtype": "gray" + } + }, + { + "name": "blur", + "executable": "ih-gaussian-blur", + "inputs": ["grayscale"], + "outputs": ["blurred"], + "arguments": { + "--kwidth": 5, + "--kheight": 5 + }, + "depends": ["gray"] + }, + { + "name": "thresh", + "executable": "ih-adaptive-threshold", + "inputs": ["blurred"], + "outputs": ["thresh"], + "arguments": { + "--value": 255, + "--thresholdType": "inverse", + "--adaptiveType": "mean", + "--blockSize": 15, + "--C": 6 + }, + "depends": ["blur"] + }, + { + "name": "reconstitute", + "executable": "ih-bitwise-and", + "inputs": ["thresh", "base"], + "outputs": ["recolor"], + "arguments": {}, + "depends": ["thresh"] + }, + { + "name": "crop", + "executable": "ih-crop", + "inputs": ["recolor", "/home/aknecht/stash/walia/ih/workflows/alexmac/input/rgbsv_edge.json"], + "outputs": ["edged"], + "arguments": {}, + "depends": ["reconstitute"] + }, + { + "name": "fill", + "executable": "ih-fill", + "inputs": ["edged", "/home/aknecht/stash/walia/ih/workflows/alexmac/input/rgbsv_pot.json"], + "outputs": ["filled"], + "arguments": {}, + "depends": ["crop"] + }, + { + "name": "cut", + "executable": "ih-contour-cut", + "inputs": ["filled", "filled"], + "outputs": ["final"], + "arguments": { + "--basemin": 50, + "--resize": "" + }, + "depends": ["fill"] + } + ] + }, + "options": { + + }, + "extract": { + "histogram-bin": { + "--group": {"rgb": ["rgbsv", "rgbtv"], "fluo": ["fluosv"]}, + "--chunks": {"rgb": [5, 5, 5], "fluo": [0, 9, 10]}, + "--channels": {"rgb": [0, 1, 2], "fluo": [1, 2]} + }, + "workflows": { + "rgbsv": { + "inputs": ["final"], + "arguments": { + "--dimensions": "", + "--pixels": "", + "--moments": "", + "--circle": "", + "--hull": "" + }, + "depends": ["cut"] + }, + "rgbtv": { + "inputs": ["final"], + "arguments": { + "--dimensions": "", + "--pixels": "", + "--moments": "", + "--circle": "", + "--hull": "" + }, + "depends": ["cut"] + }, + "fluosv": { + "inputs": ["final"], + "arguments": { + "--dimensions": "", + "--pixels": "", + "--moments": "", + "--circle": "", + "--hull": "" + }, + "depends": ["cut"] + } + } + } +} diff --git a/examples/workflows/alexmac/rgbsv_edge.json b/examples/workflows/alexmac/rgbsv_edge.json new file mode 100644 index 0000000000000000000000000000000000000000..390309028720ceb22a242199335af50dc56bda75 --- /dev/null +++ b/examples/workflows/alexmac/rgbsv_edge.json @@ -0,0 +1,6 @@ +{ + "ystart": 400, + "yend": "y", + "xstart": 400, + "xend": "x - 400" +} diff --git a/examples/workflows/alexmac/rgbsv_pot.json b/examples/workflows/alexmac/rgbsv_pot.json new file mode 100644 index 0000000000000000000000000000000000000000..1b72c0bd2de7f31ecd09d290388877fc187b5612 --- /dev/null +++ b/examples/workflows/alexmac/rgbsv_pot.json @@ -0,0 +1,6 @@ +{ + "ystart": 1746, + "yend": 2056, + "xstart": 992, + "xend": 1572 +} diff --git a/examples/workflows/alexmac/rgbtv_edge.json b/examples/workflows/alexmac/rgbtv_edge.json new file mode 100644 index 0000000000000000000000000000000000000000..04353d46377e23d1d874b7fa4b1a527ac0b959d4 --- /dev/null +++ b/examples/workflows/alexmac/rgbtv_edge.json @@ -0,0 +1,6 @@ +{ + "ystart": 350, + "yend": "y - 350", + "xstart": 350, + "xend": "x - 350" +} diff --git a/examples/workflows/blecha/config.json b/examples/workflows/blecha/config.json new file mode 100644 index 0000000000000000000000000000000000000000..52a126c8c803052abfcec272f40f1a4194cbd290 --- /dev/null +++ b/examples/workflows/blecha/config.json @@ -0,0 +1,27 @@ +{ + "version": "1.0", + "installdir": "/home/aknecht/stash/walia/ih/ih/build/scripts-2.7/", + "profile": { + "pegasus": { + "style": "condor" + }, + "condor": { + "universe": "vanilla", + "requirements": "OSGVO_OS_STRING == \"RHEL 6\" && HAS_FILE_usr_lib64_libstdc___so_6 && CVMFS_oasis_opensciencegrid_org_REVISION >= 3590", + "+WantsStashCache": "True" + } + }, + "osg": { + "tarball": "/home/aknecht/stash/walia/ih/ih/dist/ih-1.0.tar.gz", + "ssh": "/home/aknecht/.ssh/workflow" + }, + "cluster": 50, + "maxwalltime": { + "stats": 300, + "images": 3 + }, + "notify": { + "email": "avi@kurtknecht.com", + "pegasus_home": "/usr/share/pegasus/" + } +} diff --git a/examples/workflows/blecha/crawl.json b/examples/workflows/blecha/crawl.json new file mode 100644 index 0000000000000000000000000000000000000000..dc5a4809add47f77cb84197a840823d564115092 --- /dev/null +++ b/examples/workflows/blecha/crawl.json @@ -0,0 +1,42 @@ +{ + "path": "/home/aknecht/stash/9-22-15_lemnatec_images/Blecha 81315/%experiment%_%id%-%genotype%_%date%_%null%_%null%/%stype%_%view%_%angle%/0_0_0.png", + "base": "/home/aknecht/stash/9-22-15_lemnatec_images/Blecha 81315/", + "filetype": ".png", + "order": ["experiment", "id", "genotype", "date", "imgname", "imtype", "path"], + "translations": { + "imtype": { + "fluo_sv": "fluosv", + "vis_tv": "rgbtv", + "vis_sv": "rgbsv" + } + }, + "data": { + "experiment": { + "type": "value", + "value": "%experiment%" + }, + "id": { + "type": "value", + "value": "%id%" + }, + "genotype": { + "type": "value", + "value": "%genotype%" + }, + "date": { + "type": "date", + "value": "%date%", + "format": "Y-m-d" + }, + "imtype": { + "type": "value", + "translate": "true", + "value": "%stype%_%view%", + "case": "lower" + }, + "imgname": { + "type": "value", + "value": "%stype%_%view%_%angle%" + } + } +} diff --git a/examples/workflows/blecha/fluosv_edge.json b/examples/workflows/blecha/fluosv_edge.json new file mode 100644 index 0000000000000000000000000000000000000000..03f1ef17653f8d73828ff7dfb161610b18ad1ab9 --- /dev/null +++ b/examples/workflows/blecha/fluosv_edge.json @@ -0,0 +1,6 @@ +{ + "ystart": 590, + "yend": 1190, + "xstart": 219, + "xend": 799 +} diff --git a/examples/workflows/blecha/imgproc.json b/examples/workflows/blecha/imgproc.json new file mode 100644 index 0000000000000000000000000000000000000000..4583089e0d7134a945e8f4f830954c0f5e8a703c --- /dev/null +++ b/examples/workflows/blecha/imgproc.json @@ -0,0 +1,320 @@ +{ + "workflows": { + "rgbtv": [ + { + "name": "normalize", + "executable": "ih-normalize-intensity", + "inputs": ["base"], + "outputs": ["normal"], + "arguments": {} + }, + { + "name": "crop_center", + "executable": "ih-crop", + "inputs": ["normal", "rgbtv_center.json"], + "outputs": ["centeronly"], + "arguments": {}, + "depends": ["normalize"] + }, + { + "name": "green_filter", + "executable": "ih-color-filter", + "inputs": ["centeronly"], + "outputs": ["gfilter"], + "arguments": { + "--logic": "(((g - r) > 15) and ((g - b) > 15))" + }, + "depends": ["crop_center"] + }, + { + "name": "create_seed_mask", + "executable": "ih-mask", + "inputs": ["gfilter"], + "outputs": ["seedmask"], + "arguments": {}, + "depends": ["green_filter"] + }, + { + "name": "blur", + "executable": "ih-blur", + "inputs": ["normal"], + "outputs": ["blurred"], + "arguments": { + "--kwidth": 3, + "--kheight": 3 + }, + "depends": ["normalize"] + }, + { + "name": "sharpen", + "executable": "ih-add-weighted", + "inputs": ["normal", "blurred"], + "outputs": ["sharpened"], + "arguments": { + "--weight1": 1.5, + "--weight2": -0.5 + }, + "depends": ["blur"] + }, + { + "name": "extract_green", + "executable": "ih-split", + "inputs": ["sharpened"], + "outputs": ["gchannel"], + "arguments": { + "--channel": 1 + }, + "depends": ["sharpen"] + }, + { + "name": "equalize", + "executable": "ih-equalize-hist", + "inputs": ["gchannel"], + "outputs": ["equalized"], + "arguments": {}, + "depends": ["extract_green"] + }, + { + "name": "bg_cfilter", + "executable": "ih-color-filter", + "inputs": ["normal"], + "outputs": ["bg_noise"], + "arguments": { + "--logic": "(((high - low) < (i / 30)) or ((b - r) > (i / 10)))" + }, + "depends": ["normalize"] + }, + { + "name": "bgmask", + "executable": "ih-mask", + "inputs": ["bg_noise"], + "outputs": ["bg_mask"], + "arguments": {}, + "depends": ["bg_cfilter"] + }, + { + "name": "flood", + "executable": "ih-flood-fill", + "inputs": ["equalized", "bg_mask", "seedmask"], + "outputs": ["flooded"], + "arguments": { + "--low": "50", + "--high": "50", + "--writecolor": "255", + "--connectivity": 8, + "--findSeed": "", + "--binary": "" + }, + "depends": ["equalize", "bgmask", "create_seed_mask"] + }, + { + "name": "thresh", + "executable": "ih-threshold", + "inputs": ["flooded"], + "outputs": ["flood_binary"], + "arguments": { + "--thresh": 254, + "--type": "inverse" + }, + "depends": ["flood"] + }, + { + "name": "combine_with_mask", + "executable": "ih-bitwise-or", + "inputs": ["flood_binary", "bgmask"], + "outputs": ["invmask"], + "arguments": {}, + "depends": ["thresh"] + }, + { + "name": "invert", + "executable": "ih-bitwise-not", + "inputs": ["invmask"], + "outputs": ["premask"], + "arguments": {}, + "depends": ["combine_with_mask"] + }, + { + "name": "crop_edges", + "executable": "ih-crop", + "inputs": ["premask", "rgbtv_edge.json"], + "outputs": ["edged_mask"], + "depends": ["invert"] + }, + { + "name": "chop", + "executable": "ih-contour-chop", + "inputs": ["edged_mask", "edged_mask"], + "outputs": ["chopped"], + "arguments": { + "--basemin": 50 + }, + "depends": ["crop_edges"] + }, + { + "name": "erode", + "executable": "ih-morphology", + "inputs": ["chopped"], + "outputs": ["morph_erode"], + "arguments": { + "--ktype": "ellipse", + "--kwidth": 3, + "--kheight": 3, + "--morphType": "erode" + }, + "depends": ["chop"] + }, + { + "name": "dilate", + "executable": "ih-morphology", + "inputs": ["morph_erode"], + "outputs": ["morph_dilate"], + "arguments": { + "--ktype": "ellipse", + "--kwidth": 3, + "--kheight": 3, + "--morphType": "dilate" + }, + "depends": ["erode"] + }, + { + "name": "reconstitute", + "executable": "ih-bitwise-and", + "inputs": ["morph_dilate", "base"], + "outputs": ["recolor"], + "arguments": {}, + "depends": ["dilate"] + }, + { + "name": "cut", + "executable": "ih-contour-cut", + "inputs": ["recolor", "recolor"], + "outputs": ["final"], + "arguments": { + "--basemin": 50, + "--resize": "" + }, + "depends": ["reconstitute"] + } + ], + "rgbsv": [ + { + "name": "normalize", + "executable": "ih-normalize-intensity", + "inputs": ["base"], + "outputs": ["normal"], + "arguments": {} + }, + { + "name": "blur", + "executable": "ih-gaussian-blur", + "inputs": ["normal"], + "outputs": ["blurred"], + "arguments": { + "--kwidth": 5, + "--kheight": 5 + }, + "depends": ["normalize"] + }, + { + "name": "gray_filter", + "executable": "ih-color-filter", + "inputs": ["blurred"], + "outputs": ["gfiltered"], + "arguments": { + "--logic": "((high - low) > (i / 30))" + }, + "depends": ["blur"] + }, + { + "name": "pot_filter", + "executable": "ih-color-filter", + "inputs": ["gfiltered"], + "outputs": ["pfiltered"], + "arguments": { + "--logic": "((g > b) and (g > r))" + }, + "depends": ["gray_filter"] + }, + { + "name": "box_filter", + "executable": "ih-color-filter", + "inputs": ["pfiltered"], + "outputs": ["bfiltered"], + "arguments": { + "--logic": "((g > b) and (g > r))" + }, + "depends": ["pot_filter"] + }, + { + "name": "crop", + "executable": "ih-crop", + "inputs": ["bfiltered", "rgbsv_edge.json"], + "outputs": ["edged"], + "arguments": {}, + "depends": ["box_filter"] + }, + { + "name": "mask", + "executable": "ih-mask", + "inputs": ["edged"], + "outputs": ["fmask"], + "arguments": {}, + "depends": ["crop"] + }, + { + "name": "reconstitute", + "executable": "ih-bitwise-and", + "inputs": ["fmask"], + "outputs": ["recolor"], + "arguments": {}, + "depends": ["mask"] + }, + { + "name": "cut", + "executable": "ih-contour-cut", + "inputs": ["recolor", "recolor"], + "outputs": ["final"], + "arguments": { + "--basemin": 50, + "--resize": "" + }, + "depends": ["reconstitute"] + } + ] + }, + "options": { + + }, + "extract": { + "histogram-bin": { + "--group": {"rgb": ["rgbsv", "rgbtv"], "fluo": ["fluosv"]}, + "--chunks": {"rgb": [5, 5, 5], "fluo": [0, 9, 10]}, + "--channels": {"rgb": [0, 1, 2], "fluo": [1, 2]} + }, + "workflows": { + "rgbsv": { + "inputs": ["final"], + "arguments": { + "--dimensions": "", + "--pixels": "", + "--moments": "", + "--circle": "", + "--hull": "" + }, + "depends": ["cut"] + }, + "rgbtv": { + "inputs": ["final"], + "arguments": { + "--dimensions": "", + "--pixels": "", + "--moments": "", + "--circle": "", + "--hull": "" + }, + "depends": ["cut"] + } + } + } +} diff --git a/examples/workflows/blecha/rgbsv_box.json b/examples/workflows/blecha/rgbsv_box.json new file mode 100644 index 0000000000000000000000000000000000000000..548ab9d4757764d89a00e2b37161d640ef44d010 --- /dev/null +++ b/examples/workflows/blecha/rgbsv_box.json @@ -0,0 +1,6 @@ +{ + "ystart": 1931, + "yend": 2056, + "xstart": 1037, + "xstart": 1557 +} diff --git a/examples/workflows/blecha/rgbsv_edge.json b/examples/workflows/blecha/rgbsv_edge.json new file mode 100644 index 0000000000000000000000000000000000000000..8c64f5ddf595d88558864eac9370ef6a3962ce89 --- /dev/null +++ b/examples/workflows/blecha/rgbsv_edge.json @@ -0,0 +1,6 @@ +{ + "ystart": 1000, + "yend": "y", + "xstart": 400, + "xend": "x - 400" +} diff --git a/examples/workflows/blecha/rgbsv_pot.json b/examples/workflows/blecha/rgbsv_pot.json new file mode 100644 index 0000000000000000000000000000000000000000..dbe7132b0e8c648c04b86bf8f6b84af65beb1ba5 --- /dev/null +++ b/examples/workflows/blecha/rgbsv_pot.json @@ -0,0 +1,6 @@ +{ + "ystart": 1806, + "yend": 2056, + "xstart": 1107, + "xend": 1487 +} diff --git a/examples/workflows/blecha/rgbtv_center.json b/examples/workflows/blecha/rgbtv_center.json new file mode 100644 index 0000000000000000000000000000000000000000..a76caaf02b93e9c25fdd24252ff7f95f41a5d148 --- /dev/null +++ b/examples/workflows/blecha/rgbtv_center.json @@ -0,0 +1,6 @@ +{ + "ystart": 740, + "yend": 1350, + "xstart": 900, + "xend": 1520 +} diff --git a/examples/workflows/blecha/rgbtv_edge.json b/examples/workflows/blecha/rgbtv_edge.json new file mode 100644 index 0000000000000000000000000000000000000000..c48375dfd1867cccab4c689041eef534f8447671 --- /dev/null +++ b/examples/workflows/blecha/rgbtv_edge.json @@ -0,0 +1,6 @@ +{ + "ystart": 200, + "yend": "y - 200", + "xstart": 200, + "xend": "x - 200" +} diff --git a/examples/workflows/blecha/stats.json b/examples/workflows/blecha/stats.json new file mode 100644 index 0000000000000000000000000000000000000000..ee72e6a9b721f90e52bf37f6e2fb160cc48520e8 --- /dev/null +++ b/examples/workflows/blecha/stats.json @@ -0,0 +1,36 @@ +{ + "rgb": [ + { + "name": "area", + "executable": "pcv-stats-shoot-area", + "inputs": ["images"], + "outputs": ["shootarea"], + "arguments": { + "--group": { + "rgb": ["rgbsv"] + } + }, + "depends": ["bin"] + }, + { + "name": "normal", + "executable": "pcv-stats-normalize", + "inputs": ["shootarea"], + "outputs": ["normal"], + "arguments": { + "--column": "pixels" + }, + "depends": ["area"] + }, + { + "name": "threshold", + "executable": "pcv-stats-threshold", + "inputs": ["normal"], + "outputs": ["thresh"], + "arguments": { + "--thresh": 0.01 + }, + "depends": ["normal"] + } + ] +} diff --git a/ih/conf.py b/ih/conf.py index 01db04df782ba715f5a25512a7f4e8b2b72a0f7c..fb7da9c7703fec977addea51ea7ea437d9efab02 100644 --- a/ih/conf.py +++ b/ih/conf.py @@ -73,6 +73,7 @@ adaptives = { "gaussian": cv2.ADAPTIVE_THRESH_GAUSSIAN_C } + """ A dictionary used to map border-types to cv2 border codes """ @@ -617,6 +618,136 @@ valid = { } } }, + "ih-split": { + "type": "imgproc", + "inputs": ["image"], + "outputs": ["image"], + "arguments": { + "--input": { + "type": "derived", + "key": "inputs", + "index": 0, + "required": "true" + }, + "--output": { + "type": "derived", + "key": "outputs", + "index": 0, + "required": "true" + }, + "--outputdir": { + "type": "overwrite", + "value": "." + }, + "--writeblank": { + "type": "overwrite", + "required": "true", + "value": "" + }, + "--channel": { + "type": "numeric", + "validation": "list", + "value": [0, 1, 2], + "required": "true" + } + } + }, + "ih-equalize-hist": { + "type": "imgproc", + "inputs": ["image"], + "outputs": ["image"], + "arguments": { + "--input": { + "type": "derived", + "key": "inputs", + "index": 0, + "required": "true" + }, + "--output": { + "type": "derived", + "key": "outputs", + "index": 0, + "required": "true" + }, + "--outputdir": { + "type": "overwrite", + "value": "." + }, + "--writeblank": { + "type": "overwrite", + "required": "true", + "value": "" + } + } + }, + "ih-flood-fill": { + "type": "imgproc", + "inputs": ["image", "image", "image"], + "outputs": ["image"], + "arguments": { + "--input": { + "type": "derived", + "key": "inputs", + "index": 0, + "required": "true" + }, + "--mask": { + "type": "derived", + "key": "inputs", + "index": 1, + "required": "true" + }, + "--seedMask": { + "type": "derived", + "key": "inputs", + "index": 2 + }, + "--output": { + "type": "derived", + "key": "outputs", + "index": 0, + "required": "true" + }, + "--outputdir": { + "type": "overwrite", + "value": "." + }, + "--writeblank": { + "type": "overwrite", + "required": "true", + "value": "" + }, + "--low": { + "type": "string", + "required": "true" + }, + "--high": { + "type": "string", + "required": "true" + }, + "--writeColor": { + "type": "string", + "required": "true" + }, + "--connectivity": { + "type": "numeric", + "validation": "list", + "value": [4, 8] + }, + "--fixed": { + "type": "exist" + }, + "--seedx": { + "type": "numeric" + }, + "--seedy": { + "type": "numeric" + }, + "--findSeed": { + "type": "exist" + } + } + }, "ih-fill": { "type": "imgproc", "inputs": ["image", "roi"], diff --git a/ih/imgproc.py b/ih/imgproc.py index d6c96d8c9f7b1e07afe1639d7a7a3f6d6bf122b9..3d2d7e7f57a4d41b4b349d1b265159d822f0f721 100644 --- a/ih/imgproc.py +++ b/ih/imgproc.py @@ -421,6 +421,16 @@ class Image(object): self.destroy() return + def split(self, channel): + self.image = cv2.split(self.image)[channel] + return + + def equalizeHist(self): + if self._isColor(): + self.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) + self.image = cv2.equalizeHist(self.image) + return + def show(self, title = None, state = None): """ :param title: The title to give the display window, if left blank one will be created. @@ -821,6 +831,76 @@ class Image(object): else: raise Exception("Invalid morphology type, should be one of: " + ",".join(conf.morph.keys()) + ".") + def _findSeed(self, seedMask): + bname, binary = self._loadResource(seedMask) + if self._isColor(binary): + binary = cv2.cvtColor(binary, cv2.COLOR_BGR2GRAY) + contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, 2) + size = 0 + select = 0 + for cnt in contours: + if cv2.contourArea(cnt) > size: + select = cnt + size = cv2.contourArea(cnt) + return tuple(select[0][0]) + + def floodFill(self, mask, low, high, writeColor = (255, 255, 255), connectivity = 4, fixed = False, seed = (0,0), findSeed = False, seedMask = None, binary = False): + """ + :param mask: A binary image corresponding to the area you don't want to fill. + :type mask: str or np.ndarray + :param seed: The beginning point to use for filling. + :type seed: Tuple (x, y) + :param low: Maximal lower brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component. + :type low: Tuple (b, g, r) or (i,) + :param high: Maximal upper brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component. + :type high: Tuple (b, g, r) or (i,) + :param writeColor: The color to write to the filled region. Default (255, 255, 255). + :type writeColor: tuple (b, g, r) or (i,) + :param connectivity: The number of neighboring pixels to consider for the flooding operation. Should be 4 or 8. + :type connectivity: int + :param fixed: If True, calculates color differences relative to the seed. + :type fixed: boolean + :param findSeed: If True, picks a seed point based on contours in the seedMask image. + :type findSeed: boolean + :param seedMask: Binary image to select seed from. + :type seedMask: str or np.ndarray + :param binary: Specify if input image is binary. + :type binary: boolean + + This function is a wrapper to the OpenCV function `floodFill <http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#floodfill>`_. + This function floods the region of an image based on calculated color differences from neighbors or from the seed. When flooding a binary + image all input color tuples should have 1 value instead of 3. + """ + print low,high,writeColor + mname, mask = self._loadResource(mask) + if self._isColor(mask): + mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) + if binary and self._isColor(): + self.convertColor("bgr", "gray") + # Mask is required to be 2 pixels wider and taller than the image + adjmask = np.zeros((self.y + 2, self.x + 2), np.uint8) + adjmask[1:1+self.y, 1:1+self.x] = mask + channels = 3 if len(self.image.shape) == 3 else 1 + if len(low) == channels: + if len(high) == channels: + if len(writeColor) == channels: + if connectivity == 4 or connectivity == 8: + if findSeed and seedMask: + seed = self._findSeed(seedMask) + if fixed: + cv2.floodFill(self.image, adjmask, seed, writeColor, low, high, connectivity | cv2.FLOODFILL_FIXED_RANGE) + else: + cv2.floodFill(self.image, adjmask, seed, writeColor, low, high, connectivity) + else: + raise Exception("Invalid value for connectivity, should be either 4 or 8.") + else: + raise Exception("Incorrect number of values for write color. Number of values should match input image channels (%s)" % (channels,)) + else: + raise Exception("Incorrect number of values for high difference. Number of values should match input image channels (%s)" % (channels,)) + else: + raise Exception("Incorrect number of values for low difference. Number of values should match input image channels (%s)" % (channels,)) + return + def fill(self, roi, color): """ :param roi: A list corresponding to the area of the image you want. List should be of the form [ystart, yend, xstart, xend] diff --git a/scripts/ih-equalize-hist b/scripts/ih-equalize-hist new file mode 100644 index 0000000000000000000000000000000000000000..2bc81e61e49f66e1b6286b30b3e70d93ae06e208 --- /dev/null +++ b/scripts/ih-equalize-hist @@ -0,0 +1,21 @@ +#!python +import argparse +import traceback +import ih.imgproc + +parser = argparse.ArgumentParser(description = "Stretches a grayscale image to the full 0-255 intensity range.") +parser.add_argument("--input", dest="input", help="Path to input image.", required = True) +parser.add_argument("--outputdir", dest="outputdir", default=".", help="Path to write output files, if not specified use current directory.") +parser.add_argument("--output", default=None, dest="output", help="Name of output image to write, if not specified, use input image name.") +parser.add_argument("--writeblank", default=False, action="store_true", help="If errors happen, write a blank file. Used to ensure dependent files exist for pegasus workflows.") +args = parser.parse_args() + +try: + plant = ih.imgproc.Image(args.input, args.outputdir, args.output, False) + plant.equalizeHist() + plant.write() +except Exception as e: + print traceback.format_exc() + if args.writeblank: + with open(args.outputdir + "/" + args.output, "w") as wh: + wh.write("not an image.") diff --git a/scripts/ih-flood-fill b/scripts/ih-flood-fill new file mode 100644 index 0000000000000000000000000000000000000000..ea4471589cc04d6929091ac3fc92ec3a88513a85 --- /dev/null +++ b/scripts/ih-flood-fill @@ -0,0 +1,42 @@ +#!python +import argparse +import traceback +import ih.imgproc + +parser = argparse.ArgumentParser(description = "Smoothes an image based on a evenly distributed kernel.") +parser.add_argument("--input", dest="input", help="Path to input image.", required = True) +parser.add_argument("--mask", dest="mask", help="Path to mask image.", required = True) +parser.add_argument("--low", dest="low", nargs="+", type=int, help="Maximal lower brigthness/color difference.", required = True) +parser.add_argument("--high", dest="high", nargs="+", type=int, help="Maximal upper brigthness/color difference.", required = True) +parser.add_argument("--writeColor", dest="writeColor", nargs="+", type=int, help="Write Color.") +parser.add_argument("--connectivity", dest="connectivity", type=int, default=4, help="Number of neighboring pixels to consider.") +parser.add_argument("--fixed", dest="fixed", default=False, action="store_true", help="Use difference relative to the seed.") +parser.add_argument("--seedx", dest="seedx", type=int, default=0, help="X coordinate of the seed.") +parser.add_argument("--seedy", dest="seedy", type=int, default=0, help="Y coordinate of the seed.") +parser.add_argument("--findSeed", dest="findSeed", default=False, action="store_true", help="Calculate seed from a given image.") +parser.add_argument("--seedMask", dest="seedMask", help="Path to seed mask image.") +parser.add_argument("--binary", dest="binary", default=False, action="store_true", help="Specify if flood is performed on a grayscale image.") +parser.add_argument("--outputdir", dest="outputdir", default=".", help="Path to write output files, if not specified use current directory.") +parser.add_argument("--output", default=None, dest="output", help="Name of output image to write, if not specified, use input image name.") +parser.add_argument("--writeblank", default=False, action="store_true", help="If errors happen, write a blank file. Used to ensure dependent files exist for pegasus workflows.") +args = parser.parse_args() + +try: + plant = ih.imgproc.Image(args.input, args.outputdir, args.output, False) + plant.floodFill(args.mask, + tuple(args.low), + tuple(args.high), + writeColor = tuple(args.writeColor), + connectivity = args.connectivity, + fixed = args.fixed, + seed = tuple([args.seedx, args.seedy]), + findSeed = args.findSeed, + seedMask = args.seedMask, + binary = args.binary + ) + plant.write() +except Exception as e: + print traceback.format_exc() + if args.writeblank: + with open(args.outputdir + "/" + args.output, "w") as wh: + wh.write("not an image.") diff --git a/scripts/ih-split b/scripts/ih-split new file mode 100644 index 0000000000000000000000000000000000000000..6b12d0e475c3a4074fcfa748fce6687cd6a8f3d9 --- /dev/null +++ b/scripts/ih-split @@ -0,0 +1,22 @@ +#!python +import argparse +import traceback +import ih.imgproc + +parser = argparse.ArgumentParser(description = "Splits an image into channels and extracts a single one.") +parser.add_argument("--input", dest="input", help="Path to input image.", required = True) +parser.add_argument("--channel", dest="channel", type=int, help="Channel to extract.", required = True) +parser.add_argument("--outputdir", dest="outputdir", default=".", help="Path to write output files, if not specified use current directory.") +parser.add_argument("--output", default=None, dest="output", help="Name of output image to write, if not specified, use input image name.") +parser.add_argument("--writeblank", default=False, action="store_true", help="If errors happen, write a blank file. Used to ensure dependent files exist for pegasus workflows.") +args = parser.parse_args() + +try: + plant = ih.imgproc.Image(args.input, args.outputdir, args.output, False) + plant.split(args.channel) + plant.write() +except Exception as e: + print traceback.format_exc() + if args.writeblank: + with open(args.outputdir + "/" + args.output, "w") as wh: + wh.write("not an image.") diff --git a/setup.py b/setup.py index f3fe22ed674e6ceb686504c9ddb9e41ea088e132..7058356d589b682d424dd16ef39e94408cdd0533 100755 --- a/setup.py +++ b/setup.py @@ -29,6 +29,9 @@ setup( "scripts/ih-resize", "scripts/ih-mask", "scripts/ih-add-weighted", + "scripts/ih-split", + "scripts/ih-equalize-hist", + "scripts/ih-flood-fill", "scripts/ih-setup", "scripts/ih-crawl",