Hough transform: Difference between revisions

m
No edit summary
m (→‎{{header|Wren}}: Minor tidy)
 
(24 intermediate revisions by 9 users not shown)
Line 19:
BBC BASIC uses Cartesian coordinates so the image is 'upside down' compared with some other solutions.
[[Image:hough_bbc.gif|right]]
<langsyntaxhighlight lang="bbcbasic"> Width% = 320
Height% = 240
Line 65:
REPEAT
WAIT 1
UNTIL FALSE</langsyntaxhighlight>
 
=={{header|C}}==
Line 74:
{{trans|Go}}
This uses the module from the Grayscale image Task. The output image is the same as in the Go solution.
<langsyntaxhighlight lang="d">import std.math, grayscale_image;
 
Image!Gray houghTransform(in Image!Gray im,
Line 112:
.houghTransform()
.savePGM("Pentagon_hough.pgm");
}</langsyntaxhighlight>
 
=={{header|Go}}==
[[file:GoHough.png|right|thumb|Output png]]
{{trans|Python}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 132:
nimx := im.Bounds().Max.X
mimy := im.Bounds().Max.Y
 
mry = int(mry/2) * 2
him := image.NewGray(image.Rect(0, 0, ntx, mry))
draw.Draw(him, him.Bounds(), image.NewUniform(color.White),
image.ZPPoint{}, draw.Src)
 
rmax := math.Hypot(float64(nimx), float64(mimy))
Line 187:
fmt.Println(err)
}
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
{{libheader|JuicyPixels}}
<langsyntaxhighlight Haskelllang="haskell">import Control.Monad (forM_, when)
import Data.Array ((!))
import Data.Array.ST (newArray, writeArray, readArray, runSTArray)
Line 307:
_ ->
putStrLn $
"Usage: " ++ prog ++ " <image-file> <out-file.png> <width> <height>"</langsyntaxhighlight>
'''Example use:'''
<syntaxhighlight lang="text">HoughTransform Pentagon.png hough.png 360 360</langsyntaxhighlight>
 
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight lang="j">NB.*houghTransform v Produces a density plot of image y in hough space
NB. y is picture as an array with 1 at non-white points,
NB. x is resolution (width,height) of resulting image
Line 323:
rho=. <. 0.5+ h * (rho-min) % max-min NB. Rescale rho from 0 to h and round to int
|.([: <:@(#/.~) (i.h)&,)"1&.|: rho NB. consolidate into picture
)</langsyntaxhighlight>
[[Image:JHoughTransform.png|320px200px|thumb|right|Resulting viewmat image from J implementation of Hough Transform on sample pentagon image]]'''Example use:'''
<langsyntaxhighlight lang="j"> require 'viewmat'
require 'media/platimg' NB. addon required pre J8
Img=: readimg_jqtide_ jpath '~temp/pentagon.png'
viewmat 460 360 houghTransform _1 > Img</langsyntaxhighlight>
<br style="clear:both" />
 
=={{header|Java}}==
'''Code:'''
<langsyntaxhighlight Javalang="java">import java.awt.image.*;
import java.io.File;
import java.io.IOException;
Line 474:
return;
}
}</langsyntaxhighlight>
 
[[Image:JavaHoughTransform.png|640px480px|thumb|right|Output from example pentagon image]]'''Example use:'''
<pre>java HoughTransform pentagon.png JavaHoughTransform.png 640 480 100</pre>
<br style="clear:both" />
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">using ImageFeatures
 
img = fill(false,5,5)
img[3,:] .= true
 
println(hough_transform_standard(img))
</syntaxhighlight> {{output}} <pre>
Tuple{Float64,Float64}[(3.0, 1.5708)]
</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
Line 573 ⟶ 584:
val minContrast = if (args.size >= 4) 64 else args[4].toInt()
inputData(args[2].toInt(), args[3].toInt(), minContrast).writeOutputImage(args[1])
}</langsyntaxhighlight>
 
=={{header|Maple}}==
<langsyntaxhighlight Maplelang="maple">with(ImageTools):
img := Read("pentagon.png")[..,..,1]:
img_x := Convolution (img, Matrix ([[1,2,1], [0,0,0],[-1,-2,-1]])):
Line 618 ⟶ 629:
end proc:
result :=HoughTransform(img,row,col);
Embed(Scale(FitIntensity(Create(result)), 1..500,1..500));</langsyntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
 
<syntaxhighlight lang="mathematica">
<lang Mathematica>
Radon[image, Method -> "Hough"]
</syntaxhighlight>
</lang>
 
=={{header|MATLAB}}==
 
* see [[Example:Hough transform/MATLAB]]
 
=={{header|Nim}}==
{{trans|D}}
{{libheader|nimPNG}}
We use the modules from tasks “Bitmap” and “Grayscale image”, adding necessary conversions to read and write PNG files.
<syntaxhighlight lang="nim">import lenientops, math
import grayscale_image
 
const White = 255
 
func houghTransform*(img: GrayImage; hx = 460; hy = 360): GrayImage =
assert not img.isNil
assert hx > 0 and hy > 0
assert (hy and 1) == 0, "hy argument must be even"
 
result = newGrayImage(hx, hy)
result.fill(White)
 
let rMax = hypot(img.w.toFloat, img.h.toFloat)
let dr = rMax / (hy / 2)
let dTh = PI / hx
 
for y in 0..<img.h:
for x in 0..<img.w:
if img[x, y] == White: continue
for iTh in 0..<hx:
let th = dTh * iTh
let r = x * cos(th) + y * sin(th)
let iry = hy div 2 - (r / dr).toInt
if result[iTh, iry] > 0:
result[iTh, iry] = result[iTh, iry] - 1
 
 
when isMainModule:
import nimPNG
import bitmap
 
const Input = "Pentagon.png"
const Output = "Hough.png"
 
let pngImage = loadPNG24(seq[byte], Input).get()
let grayImage = newGrayImage(pngImage.width, pngImage.height)
 
# Convert to grayscale.
for i in 0..grayImage.pixels.high:
grayImage.pixels[i] = Luminance(0.2126 * pngImage.data[3 * i] +
0.7152 * pngImage.data[3 * i + 1] +
0.0722 * pngImage.data[3 * i + 2] + 0.5)
 
# Apply Hough transform and convert to an RGB image.
let houghImage = grayImage.houghTransform().toImage()
 
# Save into a PNG file.
# As nimPNG expects a sequence of bytes, not a sequence of colors, we have to make a copy.
var data = newSeqOfCap[byte](houghImage.pixels.len * 3)
for color in houghImage.pixels:
data.add([color.r, color.g, color.b])
discard savePNG24(Output, data, houghImage.w, houghImage.h)</syntaxhighlight>
 
=={{header|Perl}}==
{{trans|Sidef}}
<syntaxhighlight lang="perl">use strict;
use warnings;
 
use Imager;
 
use constant pi => 3.14159265;
 
sub hough {
my($im) = shift;
my($width) = shift || 460;
my($height) = shift || 360;
$height = 2 * int $height/2;
$height = 2 * int $height/2;
my($xsize, $ysize) = ($im->getwidth, $im->getheight);
my $ht = Imager->new(xsize => $width, ysize => $height);
my @canvas;
for my $i (0..$height-1) { for my $j (0..$width-1) { $canvas[$i][$j] = 255 } }
$ht->box(filled => 1, color => 'white');
 
my $rmax = sqrt($xsize**2 + $ysize**2);
my $dr = 2 * $rmax / $height;
my $dth = pi / $width;
 
for my $x (0..$xsize-1) {
for my $y (0..$ysize-1) {
my $col = $im->getpixel(x => $x, y => $y);
my($r,$g,$b) = $col->rgba;
next if $r==255; # && $g==255 && $b==255;
for my $k (0..$width) {
my $th = $dth*$k;
my $r2 = ($x*cos($th) + $y*sin($th));
my $iry = ($height/2 + int($r2/$dr + 0.5));
$ht->setpixel(x => $k, y => $iry, color => [ ($canvas[$iry][$k]--) x 3] );
}
}
}
return $ht;
}
 
my $img = Imager->new;
$img->read(file => 'ref/pentagon.png') or die "Cannot read: ", $img->errstr;
my $ht = hough($img);
$ht->write(file => 'hough_transform.png');
</syntaxhighlight>
 
=={{header|Phix}}==
{{libheader|Phix/pGUI}}
{{trans|Sidef}}
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Hough_transform.exw</span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- IupImage, imImage, im_width/height/pixel, allocate,
-- imFileImageLoadBitmap, IupImageFromImImage</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">hypot</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">*</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">b</span><span style="color: #0000FF;">*</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">hough_transform</span><span style="color: #0000FF;">(</span><span style="color: #000000;">imImage</span> <span style="color: #000000;">im</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">=</span><span style="color: #000000;">460</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">=</span><span style="color: #000000;">360</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">height</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">xsize</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">im_width</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ysize</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">im_height</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">255</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">),</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">rmax</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hypot</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xsize</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ysize</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">rmax</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dth</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #004600;">PI</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">ysize</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">xsize</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">im_pixel</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">255</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">width</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">th</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dth</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">r2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">th</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">th</span><span style="color: #0000FF;">))</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">iry</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r2</span><span style="color: #0000FF;">/</span><span style="color: #000000;">dr</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0.5</span><span style="color: #0000FF;">))+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">cik</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">canvas</span><span style="color: #0000FF;">[</span><span style="color: #000000;">iry</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">cik</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">canvas</span><span style="color: #0000FF;">[</span><span style="color: #000000;">iry</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cik</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">flatten</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (needed by IupImage)</span>
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">new_img</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupImage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">255</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">IupSetStrAttributeId</span><span style="color: #0000FF;">(</span><span style="color: #000000;">new_img</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d %d %d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">new_img</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">pError</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">machine_word</span><span style="color: #0000FF;">())</span>
<span style="color: #000000;">imImage</span> <span style="color: #000000;">im1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">imFileImageLoadBitmap</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Pentagon320.png"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pError</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">im1</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #008000;">"error opening Pentagon320.png"</span> <span style="color: #7060A8;">abort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">Ihandln</span> <span style="color: #000000;">image1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">IupImageFromImImage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">image2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hough_transform</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">label1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">label2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupSetAttributeHandle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">label1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"IMAGE"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">image1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttributeHandle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">label2</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"IMAGE"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">image2</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">IupHbox</span><span style="color: #0000FF;">({</span><span style="color: #000000;">label1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">label2</span><span style="color: #0000FF;">}))</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Hough transform"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (no chance...)</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
 
=={{header|Python}}==
{{libheader|PIL}}
This is the classical Hough transform as described in wikipedia. The code does not compute averages; it merely makes a point on the transformed image darker if a lot of points on the original image lie on the corresponding line. The output is almost identical to that of the Tcl code. The code works only with gray-scale images, but it is easy to extend to RGB.
<langsyntaxhighlight lang="python">
from math import hypot, pi, cos, sin
from PIL import Image
Line 671 ⟶ 852:
if __name__ == "__main__": test()
 
</syntaxhighlight>
</lang>
 
{{omit from|PARI/GP}}
 
=={{header|Racket}}==
* see [[Example:Hough transform/Racket]]
 
=={{header|Raku}}==
(formerly Perl 6)
The <code>GD</code> module the output palette to 255 colors, so only transform darker pixels in the image.
{{trans|Perl}}
<syntaxhighlight lang="raku" line>use GD;
 
my $filename = 'pentagon.ppm';
my $in = open($filename, :r, :enc<iso-8859-1>);
my ($type, $dim, $depth) = $in.lines[^3];
my ($xsize,$ysize) = split ' ', $dim;
 
my ($width, $height) = 460, 360;
my $image = GD::Image.new($width, $height);
 
my @canvas = [255 xx $width] xx $height;
 
my $rmax = sqrt($xsize**2 + $ysize**2);
my $dr = 2 * $rmax / $height;
my $dth = π / $width;
 
my $pixel = 0;
my %cstore;
for $in.lines.ords -> $r, $g, $b {
$pixel++;
next if $r > 130;
 
my $x = $pixel % $xsize;
my $y = floor $pixel / $xsize;
 
(^$width).map: -> $k {
my $th = $dth*$k;
my $r = ($x*cos($th) + $y*sin($th));
my $iry = ($height/2 + ($r/$dr).round(1)).Int;
my $c = '#' ~ (@canvas[$iry][$k]--).base(16) x 3;
%cstore{$c} = $image.colorAllocate($c) if %cstore{$c}:!exists;
$image.pixel($k, $iry, %cstore{$c});
}
}
 
my $png_fh = $image.open("hough-transform.png", "wb");
$image.output($png_fh, GD_PNG);
$png_fh.close;</syntaxhighlight>
See [https://github.com/thundergnat/rc/blob/master/img/hough-transform.png Hough Transform] (offsite .png image)
 
=={{header|Ruby}}==
 
<syntaxhighlight lang="ruby">
<lang Ruby>
require 'mathn'
require 'rubygems'
Line 714 ⟶ 939:
end
out
end</langsyntaxhighlight>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">
//! Contributed by Gavin Baker <gavinb@antonym.org>
//! Adapted from the Go version
 
use std::fs::File;
use std::io::{self, BufRead, BufReader, BufWriter, Read, Write};
use std::iter::repeat;
 
/// Simple 8-bit grayscale image
struct ImageGray8 {
width: usize,
height: usize,
data: Vec<u8>,
}
 
fn load_pgm(filename: &str) -> io::Result<ImageGray8> {
// Open file
let mut file = BufReader::new(File::open(filename)?);
 
// Read header
let mut magic_in = String::new();
let _ = file.read_line(&mut magic_in)?;
let mut width_in = String::new();
let _ = file.read_line(&mut width_in)?;
let mut height_in = String::new();
let _ = file.read_line(&mut height_in)?;
let mut maxval_in = String::new();
let _ = file.read_line(&mut maxval_in)?;
 
assert_eq!(magic_in, "P5\n");
assert_eq!(maxval_in, "255\n");
 
// Parse header
let width = width_in
.trim()
.parse::<usize>()
.map_err(|_| io::ErrorKind::InvalidData)?;
let height: usize = height_in
.trim()
.parse::<usize>()
.map_err(|_| io::ErrorKind::InvalidData)?;
 
println!("Reading pgm file {}: {} x {}", filename, width, height);
 
// Create image and allocate buffer
let mut img = ImageGray8 {
width,
height,
data: vec![],
};
 
// Read image data
let expected_bytes = width * height;
let bytes_read = file.read_to_end(&mut img.data)?;
if bytes_read != expected_bytes {
let kind = if bytes_read < expected_bytes {
io::ErrorKind::UnexpectedEof
} else {
io::ErrorKind::InvalidData
};
let msg = format!("expected {} bytes", expected_bytes);
return Err(io::Error::new(kind, msg));
}
 
Ok(img)
}
 
fn save_pgm(img: &ImageGray8, filename: &str) {
// Open file
let mut file = BufWriter::new(File::create(filename).unwrap());
 
// Write header
if let Err(e) = writeln!(&mut file, "P5\n{}\n{}\n255", img.width, img.height) {
println!("Failed to write header: {}", e);
}
 
println!(
"Writing pgm file {}: {} x {}",
filename, img.width, img.height
);
 
// Write binary image data
if let Err(e) = file.write_all(&(img.data[..])) {
println!("Failed to image data: {}", e);
}
}
 
#[allow(clippy::cast_precision_loss)]
#[allow(clippy::clippy::cast_possible_truncation)]
fn hough(image: &ImageGray8, out_width: usize, out_height: usize) -> ImageGray8 {
let in_width = image.width;
let in_height = image.height;
 
// Allocate accumulation buffer
let out_height = ((out_height / 2) * 2) as usize;
let mut accum = ImageGray8 {
width: out_width,
height: out_height,
data: repeat(255).take(out_width * out_height).collect(),
};
 
// Transform extents
let rmax = (in_width as f64).hypot(in_height as f64);
let dr = rmax / (out_height / 2) as f64;
let dth = std::f64::consts::PI / out_width as f64;
 
// Process input image in raster order
for y in 0..in_height {
for x in 0..in_width {
let in_idx = y * in_width + x;
let col = image.data[in_idx];
if col == 255 {
continue;
}
 
// Project into rho,theta space
for jtx in 0..out_width {
let th = dth * (jtx as f64);
let r = (x as f64) * (th.cos()) + (y as f64) * (th.sin());
 
let iry = out_height as i64 / 2 - (r / (dr as f64) + 0.5).floor() as i64;
#[allow(clippy::clippy::cast_sign_loss)]
let out_idx = (jtx as i64 + iry * out_width as i64) as usize;
let col = accum.data[out_idx];
if col > 0 {
accum.data[out_idx] = col - 1;
}
}
}
}
accum
}
 
fn main() -> io::Result<()> {
let image = load_pgm("resources/Pentagon.pgm")?;
let accum = hough(&image, 460, 360);
save_pgm(&accum, "hough.pgm");
Ok(())
}
 
</syntaxhighlight>
 
 
=={{header|Scala}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="scala">import java.awt.image._
import java.io.File
import javax.imageio._
Line 800 ⟶ 1,169:
 
private val dataArray = Array.ofDim[Int](width, height)
}</langsyntaxhighlight>
 
=={{header|SequenceL}}==
{{trans|Java}}
'''Tail-Recursive SequenceL Code:'''<br>
<langsyntaxhighlight lang="sequencel">import <Utilities/Sequence.sl>;
import <Utilities/Math.sl>;
 
Line 849 ⟶ 1,218:
j within x-1 ... x+1;
in
some(some(abs(image[y,x] - neighbors) >= minContrast));</langsyntaxhighlight>
 
'''C++ Driver Code:'''<br>
{{libheader|CImg}}
<langsyntaxhighlight lang="c">#include "SL_Generated.h"
#include "CImg.h"
 
Line 891 ⟶ 1,260:
sl_done();
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 898 ⟶ 1,267:
=={{header|Sidef}}==
{{trans|Python}}
<langsyntaxhighlight lang="ruby">require('Imager')
 
func hough(im, width=460, height=360) {
Line 933 ⟶ 1,302:
var img = %s|Imager|.new(file => 'Pentagon.png')
var ht = hough(img)
ht.write(file => 'Hough transform.png')</langsyntaxhighlight>
 
=={{header|Tcl}}==
Line 939 ⟶ 1,308:
 
* See [[Example:Hough transform/Tcl]]
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|DOME}}
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color, ImageData
import "dome" for Window, Process
import "math" for Math
 
var Hypot = Fn.new { |x, y| (x*x + y*y).sqrt }
 
class ArrayData {
construct new(width, height) {
_width = width
_height = height
_dataArray = List.filled(width * height, 0)
}
 
width { _width }
height { _height }
 
[x, y] { _dataArray[y * _width + x] }
 
[x, y]=(v) { _dataArray[y * _width + x] = v }
 
transform(thetaAxisSize, rAxisSize, minContrast) {
var maxRadius = Math.ceil(Hypot.call(_width, _height))
var halfRAxisSize = rAxisSize >> 1
var outputData = ArrayData.new(thetaAxisSize, rAxisSize)
// x output ranges from 0 to pi
// y output ranges from -maxRadius to maxRadius
var sinTable = List.filled(thetaAxisSize, 0)
var cosTable = List.filled(thetaAxisSize, 0)
for (theta in thetaAxisSize - 1..0) {
var thetaRadians = theta * Num.pi / thetaAxisSize
sinTable[theta] = Math.sin(thetaRadians)
cosTable[theta] = Math.cos(thetaRadians)
}
for (y in _height - 1..0) {
for (x in _width - 1..0) {
if (contrast(x, y, minContrast)) {
for (theta in thetaAxisSize - 1..0) {
var r = cosTable[theta] * x + sinTable[theta] * y
var rScaled = Math.round(r * halfRAxisSize / maxRadius) + halfRAxisSize
outputData.accumulate(theta, rScaled, 1)
}
}
}
}
return outputData
}
 
accumulate(x, y, delta) { this[x, y] = this[x, y] + delta }
 
contrast(x, y, minContrast) {
var centerValue = this[x, y]
for (i in 8..0) {
if (i != 4) {
var newx = x + i % 3 - 1
var newy = y + (i / 3).truncate - 1
if (newx >= 0 && newx < width && newy >= 0 && newy < height &&
Math.abs(this[newx, newy] - centerValue) >= minContrast) return true
}
}
return false
}
 
max {
var max = _dataArray[0]
for (i in width * height - 1..1) {
if (_dataArray[i] > max) max = _dataArray[i]
}
return max
}
}
 
class HoughTransform {
construct new(inFile, outFile, width, height, minCont) {
Window.title = "Hough Transform"
Window.resize(width, height)
Canvas.resize(width, height)
_width = width
_height = height
_inFile = inFile
_outFile = outFile
_minCont = minCont
}
 
init() {
var dataArray = readInputFromImage(_inFile)
dataArray = dataArray.transform(_width, _height, _minCont)
writeOutputImage(_outFile, dataArray)
}
 
readInputFromImage(filename) {
var inputImage = ImageData.load(filename)
var width = inputImage.width
var height = inputImage.height
var rgbData = []
for (y in 0...height) {
for (x in 0...width) rgbData.add(inputImage.pget(x, y))
}
var arrayData = ArrayData.new(width, height)
// Flip y axis when reading image
for (y in 0...height) {
for (x in 0...width) {
var rgbValue = rgbData[y * width + x]
rgbValue = (rgbValue.r * 0.3 + rgbValue.g * 0.59 + rgbValue.b * 0.11).floor
arrayData[x, height - 1 - y] = rgbValue
}
}
return arrayData
}
 
writeOutputImage(filename, arrayData) {
var max = arrayData.max
var outputImage = ImageData.create(filename, arrayData.width, arrayData.height)
for (y in 0...arrayData.height) {
for (x in 0...arrayData.width) {
var n = Math.min(Math.round(arrayData[x, y] * 255 / max), 255)
var c = Color.new(n, n, 0x90)
outputImage.pset(x, arrayData.height - 1 - y, c)
}
}
outputImage.draw(0, 0)
outputImage.saveToFile(filename)
}
 
update() {}
 
draw(alpha) {}
}
 
var args = Process.args
System.print(args)
if (args.count != 7) Fiber.abort("There should be exactly 5 command line arguments.")
var inFile = args[2]
var outFile = args[3]
var width = Num.fromString(args[4])
var height = Num.fromString(args[5])
var minCont = Num.fromString(args[6])
var Game = HoughTransform.new(inFile, outFile, width, height, minCont)</syntaxhighlight>
 
{{out}}
<pre>
When called with: 'dome hough_transform.wren Pentagon.png Pentagon2.png 640 480 100' the resulting image is similar to that of the Java entry.
</pre>
 
=={{header|zkl}}==
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
{{trans|D}}
<langsyntaxhighlight lang="zkl">const WHITE=0xffFFff, X=0x010101;
fcn houghTransform(image,hx=460,hy=360){
if(hy.isOdd) hy-=1; // hy argument must be even
Line 959 ⟶ 1,474:
}
out
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="zkl">fcn readPNG2PPM(fileName){
p:=System.popen("convert \"%s\" ppm:-".fmt(fileName),"r");
img:=PPM.readPPM(p);
Line 968 ⟶ 1,483:
}
houghTransform(readPNG2PPM("pentagon.png"))
.write(File("pentagon_hough.ppm","wb"));</langsyntaxhighlight>
{{out}}
The output image looks the same as in the Go solution.
9,482

edits