{"id":20,"date":"2015-02-18T20:09:19","date_gmt":"2015-02-18T20:09:19","guid":{"rendered":"http:\/\/sissv.activearchives.org\/logbook\/?p=20"},"modified":"2015-03-08T13:48:56","modified_gmt":"2015-03-08T13:48:56","slug":"image-gradients","status":"publish","type":"post","link":"https:\/\/sicv.activearchives.org\/logbook\/image-gradients\/","title":{"rendered":"Image gradients"},"content":{"rendered":"<p><span class=\"imagegradient\" data-mode=\"grid\"><a class=\"source\" href=\"\/imagegradients\/01_17_IMG_6262WEB.jpg\">image<\/a><a class=\"gradient\" href=\"\/imagegradients\/01_17_IMG_6262WEB.gradient.png\">gradient<\/a><\/span><br \/>\nImage gradients are a fundamental transformation used in image processing, search indexing, and computer vision. Like a weather map showing the direction and strength of the wind, an image gradient depicts the strength and direction of changes in intensity over the surface of the image.<br \/>\n<script src=\"\/lib\/imagegradient.js\"><\/script><br \/>\n<!--more--><br \/>\nThrough a fluke in my interpretation \/ understanding of the technique the gradients shown here on of images of objects from the Guttormsgaard archive, follow not the direction of the change but rather its perpendicular. As a result, the arrows chase around the edges of objects rather than piercing straight into them. Indeed, the image gradients shares a close affiliation between with the operation of edge-detection (where the movements are further segmented into discrete segments).<\/p>\n<p><span class=\"imagegradient\" data-mode=\"grid\"><a class=\"source\" href=\"\/imagegradients\/01_40_IMG_6294WEB.jpg\">01_40_IMG_6294WEB.jpg<\/a><a class=\"gradient\" href=\"\/imagegradients\/01_40_IMG_6294WEB.gradient.png\">01_40_IMG_6294WEB.jpg<\/a><\/span><br \/>\n<span class=\"imagegradient\"><a class=\"source\" href=\"\/imagegradients\/12_IMG_2406WEB.jpg\">12_IMG_2406WEB.jpg<\/a><a class=\"gradient\" href=\"\/imagegradients\/12_IMG_2406WEB.gradient.png\">12_IMG_2406WEB.jpg<\/a><\/span><br \/>\n<span class=\"imagegradient\"><a class=\"source\" data-mode=\"image\" href=\"\/imagegradients\/12c_IMG_5525WEB.jpg\">12c_IMG_5525WEB.jpg<\/a><a class=\"gradient\" data-mode=\"image\" href=\"\/imagegradients\/12c_IMG_5525WEB.gradient.png\">12c_IMG_5525WEB.jpg<\/a><\/span><br \/>\n<span class=\"imagegradient\"><a class=\"source\" href=\"\/imagegradients\/13a_MG_8326WEB.jpg\">13a_MG_8326WEB.jpg<\/a><a class=\"gradient\" href=\"\/imagegradients\/13a_MG_8326WEB.gradient.png\">13a_MG_8326WEB.jpg<\/a><\/span><br \/>\n<span class=\"imagegradient\"><a class=\"source\" href=\"\/imagegradients\/15_IMG_2418WEB.jpg\">15_IMG_2418WEB.jpg<\/a><a class=\"gradient\" href=\"\/imagegradients\/15_IMG_2418WEB.gradient.png\">15_IMG_2418WEB.jpg<\/a><\/span><br \/>\n<span class=\"imagegradient\"><a class=\"source\" href=\"\/imagegradients\/18_IMG_2430WEB.jpg\">18_IMG_2430WEB.jpg<\/a><a class=\"gradient\" href=\"\/imagegradients\/18_IMG_2430WEB.gradient.png\">18_IMG_2430WEB.jpg<\/a><\/span><br \/>\n<span class=\"imagegradient\"><a class=\"source\" href=\"\/imagegradients\/19a_IMG_0424Web.jpg\">19a_IMG_0424Web.jpg<\/a><a class=\"gradient\" href=\"\/imagegradients\/19a_IMG_0424Web.gradient.png\">19a_IMG_0424Web.jpg<\/a><\/span><\/p>\n<p>Following the description of Image derivatives in the book <a href=\"http:\/\/programmingcomputervision.com\/\">Programming Computer Vision with Python<\/a> (p. 18), the following python code uses gaussian filters to approximate the derivative (rate of change) in first the x and the the y directions, and then uses a square root function to find the magnitude of change, and an arc tangent function to find the direction (or its perpendicular) at each point. The results are used to construct a second &#8220;gradient image&#8221; where the pixels color (hue in degrees on the HSL color wheel) represent the direction, and the value (or lightness) the magnitude of change.<\/p>\n<p>On this page, clicking on the image switches between 3 views: (1) drawing the gradient at the mouse location, (2) drawing a grid of equally spaced gradients, and (3) showing the underlying (and pre-calated) &#8220;hsl&#8221; gradient image, which is the source of data used to perform the first two views.<\/p>\n<pre lang=\"python\">\r\n#!\/usr\/bin\/python\r\n\r\nfrom PIL import Image\r\nfrom numpy import *\r\nfrom scipy.ndimage import filters\r\nimport sys, json, os, math\r\nfrom hsl import hsl_to_rgb\r\nimport argparse\r\n\r\n# Based on Programming Computer Vision, chapter 1, Image Derivatives\r\n\r\nparser = argparse.ArgumentParser(description='Calculate an image gradient.')\r\nparser.add_argument('input', help='an image path as input')\r\nparser.add_argument('--format', default=\"hslimage\", help='save output format, default hslimage (direction is hue, magnitude is lightness). Other options: magimage (magnitude image), json.')\r\nparser.add_argument('--output', help='save to output path')\r\nargs = parser.parse_args()\r\np = args.input\r\npath, base = os.path.split(p)\r\nbase, ext = os.path.splitext(base)\r\nout = args.output or os.path.join(path, base + \".gradient.png\")\r\nim = array(Image.open(p).convert('L'))\r\n\r\nsigma = 5 # standard deviation\r\nimx = zeros(im.shape)\r\nfilters.gaussian_filter(im, (sigma,sigma), (0,1), imx)\r\nimy = zeros(im.shape)\r\nfilters.gaussian_filter(im, (sigma,sigma), (1,0), imy)\r\nmagnitude = sqrt(imx**2+imy**2)\r\ndirs = arctan2(imy, imx)\r\n\r\nif args.format == \"hslimage\":\r\n    # Map direction to Hue, Magnitude to value\r\n    from math import pi\r\n    maxmag = amax(magnitude)\r\n    height, width = magnitude.shape\r\n    im = Image.new(\"RGBA\", (width, height))\r\n    for y in range(height):\r\n        p = int(math.ceil(float(y)\/height*100))\r\n        sys.stderr.write(\"\\rCreating gradient HSL image... [{0}%]\".format(p))\r\n        sys.stderr.flush()\r\n        for x in range(width):\r\n            d = dirs[y][x]\r\n            hue = ((d+pi) \/ (2 * pi)) * 360\r\n            value = (magnitude[y][x]\/maxmag)\r\n            r, g, b = hsl_to_rgb(hue, 1.0, value)\r\n            im.putpixel((x, y), (r, g, b, 255))\r\n    sys.stderr.write(\"\\n\")\r\n    im.save(out)\r\nelif args.format == \"magimage\":\r\n    pil_im = Image.fromarray(magnitude)\r\n    pil_im.convert(\"LA\").save(out)\r\nelif args.format == \"json\":\r\n    with open(out, \"w\") as f:\r\n        json.dump({\r\n            'dirs': dirs.tolist(),\r\n            'magnitudes': magnitude.tolist()\r\n        }, f)\r\n\r\n<\/pre>\n<p>The code is <a href=\"https:\/\/gitorious.org\/sissv\/imagegradient\">published here<\/a>.<\/p>\n<p><script src=\"\/lib\/imagegradient.js\"><\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>imagegradient Image gradients are a fundamental transformation used in image processing, search indexing, and computer vision. Like a weather map showing the direction and strength of the wind, an image gradient depicts the strength and direction of changes in intensity over the surface of the image.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[17,16,9,10],"_links":{"self":[{"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/posts\/20"}],"collection":[{"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/comments?post=20"}],"version-history":[{"count":25,"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/posts\/20\/revisions"}],"predecessor-version":[{"id":102,"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/posts\/20\/revisions\/102"}],"wp:attachment":[{"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/media?parent=20"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/categories?post=20"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sicv.activearchives.org\/logbook\/wp-json\/wp\/v2\/tags?post=20"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}