September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -5,22 +5,30 @@ import qualified Data.Foldable as F (maximum)
|
|||
import System.Environment (getArgs, getProgName)
|
||||
|
||||
-- Library JuicyPixels:
|
||||
import Codec.Picture (DynamicImage(ImageRGB8, ImageRGBA8), Image,
|
||||
PixelRGB8(PixelRGB8), PixelRGBA8(PixelRGBA8),
|
||||
imageWidth, imageHeight, pixelAt, generateImage,
|
||||
readImage, pixelMap, savePngImage)
|
||||
import Codec.Picture
|
||||
(DynamicImage(ImageRGB8, ImageRGBA8), Image, PixelRGB8(PixelRGB8),
|
||||
PixelRGBA8(PixelRGBA8), imageWidth, imageHeight, pixelAt,
|
||||
generateImage, readImage, pixelMap, savePngImage)
|
||||
import Codec.Picture.Types (extractLumaPlane, dropTransparency)
|
||||
|
||||
dot :: Num a => (a, a) -> (a, a) -> a
|
||||
dot
|
||||
:: Num a
|
||||
=> (a, a) -> (a, a) -> a
|
||||
dot (x1, y1) (x2, y2) = x1 * x2 + y1 * y2
|
||||
|
||||
mag :: Floating a => (a, a) -> a
|
||||
mag
|
||||
:: Floating a
|
||||
=> (a, a) -> a
|
||||
mag a = sqrt $ dot a a
|
||||
|
||||
sub :: Num a => (a, a) -> (a, a) -> (a, a)
|
||||
sub
|
||||
:: Num a
|
||||
=> (a, a) -> (a, a) -> (a, a)
|
||||
sub (x1, y1) (x2, y2) = (x1 - x2, y1 - y2)
|
||||
|
||||
fromIntegralP :: (Integral a, Num b) => (a, a) -> (b, b)
|
||||
fromIntegralP
|
||||
:: (Integral a, Num b)
|
||||
=> (a, a) -> (b, b)
|
||||
fromIntegralP (x, y) = (fromIntegral x, fromIntegral y)
|
||||
|
||||
{-
|
||||
|
|
@ -39,63 +47,59 @@ hough image thetaSize distSize = hImage
|
|||
hMax = height - 1
|
||||
xCenter = wMax `div` 2
|
||||
yCenter = hMax `div` 2
|
||||
|
||||
lumaMap = extractLumaPlane image
|
||||
|
||||
gradient x y =
|
||||
let orig = pixelAt lumaMap x y
|
||||
x' = pixelAt lumaMap (min (x + 1) wMax) y
|
||||
y' = pixelAt lumaMap x (min (y + 1) hMax)
|
||||
in fromIntegralP (orig - x', orig - y')
|
||||
|
||||
gradMap = [((x, y), gradient x y) | x <- [0..wMax], y <- [0..hMax]]
|
||||
|
||||
x_ = pixelAt lumaMap (min (x + 1) wMax) y
|
||||
y_ = pixelAt lumaMap x (min (y + 1) hMax)
|
||||
in fromIntegralP (orig - x_, orig - y_)
|
||||
gradMap =
|
||||
[ ((x, y), gradient x y)
|
||||
| x <- [0 .. wMax]
|
||||
, y <- [0 .. hMax] ]
|
||||
-- The longest distance from the center, half the hypotenuse of the image.
|
||||
distMax :: Double
|
||||
distMax = (sqrt . fromIntegral $ height ^ 2 + width ^ 2) / 2
|
||||
|
||||
{-
|
||||
The accumulation bins of the polar values.
|
||||
For each value in the gradient image, if the gradient length exceeds
|
||||
some threshold, consider it evidence of a line and plot all of the
|
||||
lines that go through that point in Hough space.
|
||||
-}
|
||||
accBin = runSTArray $ do
|
||||
arr <- newArray ((0, 0), (thetaSize, distSize)) 0
|
||||
forM_ gradMap $ \((x, y), grad) -> do
|
||||
let (x', y') = fromIntegralP $ (xCenter, yCenter) `sub` (x, y)
|
||||
|
||||
when (mag grad > 127) $
|
||||
forM_ [0..thetaSize] $ \theta -> do
|
||||
let theta' = (fromIntegral theta) * 360 / (fromIntegral thetaSize)
|
||||
/ 180 * pi :: Double
|
||||
dist = (cos theta' * x' + sin theta' * y')
|
||||
dist' = truncate $ dist * (fromIntegral distSize) / distMax
|
||||
idx = (theta, dist')
|
||||
|
||||
when (dist' >= 0 && dist' < distSize) $ do
|
||||
old <- readArray arr idx
|
||||
writeArray arr idx $ old + 1
|
||||
|
||||
return arr
|
||||
|
||||
accBin =
|
||||
runSTArray $
|
||||
do arr <- newArray ((0, 0), (thetaSize, distSize)) 0
|
||||
forM_ gradMap $
|
||||
\((x, y), grad) -> do
|
||||
let (x_, y_) = fromIntegralP $ (xCenter, yCenter) `sub` (x, y)
|
||||
when (mag grad > 127) $
|
||||
forM_ [0 .. thetaSize] $
|
||||
\theta -> do
|
||||
let theta_ =
|
||||
fromIntegral theta * 360 / fromIntegral thetaSize / 180 *
|
||||
pi :: Double
|
||||
dist = cos theta_ * x_ + sin theta_ * y_
|
||||
dist_ = truncate $ dist * fromIntegral distSize / distMax
|
||||
idx = (theta, dist_)
|
||||
when (dist_ >= 0 && dist_ < distSize) $
|
||||
do old <- readArray arr idx
|
||||
writeArray arr idx $ old + 1
|
||||
return arr
|
||||
maxAcc = F.maximum accBin
|
||||
|
||||
-- The image representation of the accumulation bins.
|
||||
hTransform x y =
|
||||
let l = 255 - (truncate $ (accBin ! (x, y)) / maxAcc * 255)
|
||||
let l = 255 - truncate ((accBin ! (x, y)) / maxAcc * 255)
|
||||
in PixelRGB8 l l l
|
||||
|
||||
hImage = generateImage hTransform thetaSize distSize
|
||||
|
||||
houghIO :: FilePath -> FilePath -> Int -> Int -> IO ()
|
||||
houghIO path outpath thetaSize distSize = do
|
||||
image <- readImage path
|
||||
case image of
|
||||
Left err -> putStrLn err
|
||||
Right (ImageRGB8 image') -> doImage image'
|
||||
Right (ImageRGBA8 image') -> doImage $ pixelMap dropTransparency image'
|
||||
_ -> putStrLn $ "Expecting RGB8 or RGBA8 image"
|
||||
Left err -> putStrLn err
|
||||
Right (ImageRGB8 image_) -> doImage image_
|
||||
Right (ImageRGBA8 image_) -> doImage $ pixelMap dropTransparency image_
|
||||
_ -> putStrLn "Expecting RGB8 or RGBA8 image"
|
||||
where
|
||||
doImage image = do
|
||||
let houghImage = hough image thetaSize distSize
|
||||
|
|
@ -108,4 +112,6 @@ main = do
|
|||
case args of
|
||||
[path, outpath, thetaSize, distSize] ->
|
||||
houghIO path outpath (read thetaSize) (read distSize)
|
||||
_ -> putStrLn $ "Usage: " ++ prog ++ " <image-file> <out-file.png> <width> <height>"
|
||||
_ ->
|
||||
putStrLn $
|
||||
"Usage: " ++ prog ++ " <image-file> <out-file.png> <width> <height>"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
require 'viewmat media/platimg'
|
||||
Img=: readimg jpath '~temp/pentagon.png'
|
||||
require 'viewmat'
|
||||
require 'media/platimg' NB. addon required pre J8
|
||||
Img=: readimg_jqtide_ jpath '~temp/pentagon.png'
|
||||
viewmat 460 360 houghTransform _1 > Img
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import java.awt.image.*
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.File
|
||||
import javax.imageio.*
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
internal class ArrayData(val dataArray: IntArray, val width: Int, val height: Int) {
|
||||
|
||||
constructor(width: Int, height: Int) : this(IntArray(width * height), width, height) {
|
||||
}
|
||||
constructor(width: Int, height: Int) : this(IntArray(width * height), width, height)
|
||||
|
||||
operator fun get(x: Int, y: Int) = dataArray[y * width + x]
|
||||
|
||||
|
|
|
|||
17
Task/Hough-transform/Zkl/hough-transform-1.zkl
Normal file
17
Task/Hough-transform/Zkl/hough-transform-1.zkl
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
const WHITE=0xffFFff, X=0x010101;
|
||||
fcn houghTransform(image,hx=460,hy=360){
|
||||
if(hy.isOdd) hy-=1; // hy argument must be even
|
||||
out:=PPM(hx,hy,WHITE);
|
||||
rMax:=image.w.toFloat().hypot(image.h);
|
||||
dr,dTh:=rMax/(hy/2), (0.0).pi/hx;
|
||||
|
||||
foreach y,x in (image.h,image.w){
|
||||
if(image[x,y]==WHITE) continue;
|
||||
foreach iTh in (hx){
|
||||
th,r:=dTh*iTh, th.cos()*x + th.sin()*y;
|
||||
iry:=hy/2 + (r/dr + 0.5).floor(); // y==0 is top
|
||||
if(out[iTh,iry]>0) out[iTh,iry]=out[iTh,iry] - X;
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
8
Task/Hough-transform/Zkl/hough-transform-2.zkl
Normal file
8
Task/Hough-transform/Zkl/hough-transform-2.zkl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fcn readPNG2PPM(fileName){
|
||||
p:=System.popen("convert \"%s\" ppm:-".fmt(fileName),"r");
|
||||
img:=PPM.readPPM(p);
|
||||
p.close();
|
||||
img
|
||||
}
|
||||
houghTransform(readPNG2PPM("pentagon.png"))
|
||||
.write(File("pentagon_hough.ppm","wb"));
|
||||
Loading…
Add table
Add a link
Reference in a new issue