Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary Hough transform implementation #14

Merged
merged 5 commits into from
Jun 12, 2018

Conversation

khilanravani
Copy link

We first extract some information from the image - width, height etc. , convert to luma and compute gradients. Then, for each pixel (x,y), we compute rho = xcos (theta) + ysin (theta). After a few more transformations and finding the bins with highest values, we generate the resulting image.

We first extract some information from the image - width, height etc., convert
to luma and compute gradients. Then, for each pixel (x,y), we compute rho = xcos(theta) + ysin(theta).
After a few more transformations and finding the bins with highest values, we generate the
resulting image.
@lehins
Copy link
Owner

lehins commented May 28, 2018

Good job @khilanravani, this looks like good progress. Besides the comments on the code itself here is one thing I'd like to see, namely Hough transform in action. Use a sample image and detect some lines in it, for instance, and then add the resulting image to the repo with example code how you generated it. For example you can use the yield.jpg image, that I think would work great for line detection, similar to how it's done in the documentation of this function: https://www.stackage.org/haddock/lts-10.10/hip-1.5.3.0/Graphics-Image-Processing-Binary.html#v:thresholdWith

@khilanravani
Copy link
Author

khilanravani commented May 28, 2018 via email

@lehins
Copy link
Owner

lehins commented May 28, 2018

I didn't exactly understand if you want me to write a
separate function for detecting lines or you are asking me to use this
hough transform and then apply it to detect lines in an image.

What I mean is adding a good example that can be used in the documentation of the function, that demonstrates not only how to use the function but also the result produced by it. There is no need to add more sample images to the repo, that's why I suggested using yield.jpg file for the mentioned example.

Also what would be nice is to see Hough transform in action. Simply looking at an image produced by hough function isn't particularly interesting, would you agree? But if there is an example of actually using the result of Hough transform that would be awesome, eg. drawing detected lines on the source image would be cool. For example page 31 of this slides: https://www.uio.no/studier/emner/matnat/ifi/INF4300/h09/undervisningsmateriale/hough09.pdf
At the same time it might be a little bit of a complicated task for now and we can defer till later.

@khilanravani
Copy link
Author

khilanravani commented May 28, 2018 via email

@lehins
Copy link
Owner

lehins commented May 28, 2018

I'll try to spend some time for doing it but if you I agree, it will be better if we postpone it

Yeah, that's fine. Go ahead and try resolving the rest of the comments I made and than I'll I'll guide you on further improvements that can be made.

@khilanravani
Copy link
Author

khilanravani commented May 28, 2018 via email

@alpmestan
Copy link

@lehins Did you forget to send all your review comments?

Copy link
Owner

@lehins lehins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alpmestan I sure did, thank you for pointing it out :)


-- | Some helper functions :
-- | toImageY : Converts an image to Luma Image
toImageY :: (ToY cs e, IP.Array arr cs e, IP.Array arr Y Double) =>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry sir. Will correct that.

-- bright (or dark, depending on the color of the background field) spot; by applying a suitable
-- filter to the results of the transform, it is possible to extract the locations of the lines in the original image.
--
-- <<images/frog_rbg.jpg>>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

frog_rbg.jpg That's a terrible image to use as an example, have you looked at it :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes sir, I'll change it.

distMax :: Double -- Compute Maximum distance
distMax = (sqrt . fromIntegral $ (heightMax + 1) ^ (2 :: Int) + (widthMax + 1) ^ (2 :: Int)) / 2

accBin = runSTArray $ -- Core part of Algo begins here. Working in a safe way with a mutable array.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to write faster code, try researching and understanding difference between "Boxed" and "Unboxed" values in Haskell. For example using runSTUArray here instead of runSTArray together with import of Data.Array.Unboxed instead of Data.Array would give you a significant speed up.
You don't need to do that here now, since in the end there will be no dependency on array package anyways, there are better ways to do that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok sir.

hImage = makeImage (thetaSz, distSz) hTransform


test :: IO ()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test functions like that have no place being in a library module.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry sir, that was for my testing. Forgot to remove it. Will do.


maxAcc = F.maximum accBin
hTransform (x, y) =
let l = 255 - truncate ((accBin ! (x, y)) / maxAcc * 255) -- pixel generating function
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pixels with Double precision are kept in the range [0, 1], not [0, 255],which is the range for Word8. So this is certainly a bug.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@khilanravani, I apologize, you original code was correct, hTransform :: (Int, Int) -> Image arr cs Word8, not a Double, so it does need to be 255 - truncate ((accBin ! (x, y)) / maxAcc * 255)

heightMax = ((cols image) - 1)
yCtr = (heightMax `div` 2)

luma :: Image arr Y Double
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no point of converting an RGB image into luma. If that is what the function needs than hough function should accept and return Y type images.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes sir, actually earlier I used RGBA images but then switched to rgb. I'll change the input type.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant by the comment above is that if hough works with luma images, then it should accept luma images not RGB or RGBA, it needs Y. So you don't need to use toImageY, the user of the hough function will. Here is what a proposed type signature might look like:

hough
  :: ( MArray arr Y Double, IP.Array arr Y Double )
  => Image arr Y Double
  -> Int
  -> Int
  -> Image arr Y Double

Unless I am mistaken, you don't need forall arr a, nor do you need either one of RankNTypes or ScopedTypeVariables extension up top.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mistaken, I see now, you do need forall arr and ScopedTypeVariables, but not the RankNTypes

So the signature will be something along those lines:

hough
  :: forall arr . ( MArray arr Y Double, IP.Array arr Y Double, IP.Array arr Y Word8)
  => Image arr Y Double
  -> Int
  -> Int
  -> Image arr Y Word8

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok sir, I'll change it accordingly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok sir, I'll change that.

, MArray arr Y Double, IP.Array arr Y Double
, IP.Array arr RGB Double
)
=> Image arr RGB a
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding was that Hough transform works on Binary images, but I haven't really studied it in depth to really understand it. So, convince me that it works correctly and than I'll guide you through on how to improve the code quality and speed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sir, as per my understanding, Hough transform is most commonly used in combination with canny, sobel or sometimes with de-noising filters. In that case, the input image is generally pre-processed and converted to binary or grayscale (more preferred). The basic concept of Hough doesn't limit its usage to binary images only although it depends on what exactly we use it for. I checked some other implementations and found that they also use grayscale images in most cases. So, I guess taking rgba as input, converting to luma and applying the algorithm shouldn't be a problem. Please correct me if I'm misunderstanding some point here.

Copy link
Author

@khilanravani khilanravani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ignore this commit.

-- filter to the results of the transform, it is possible to extract the locations of the lines in the original image.
--
-- <<images/yield.jpg>>
--
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please include the result image of applying the hough transform to yield.jpg here.
This way a user will know what sort of result to expect.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure sir, will do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure sir, will do so.

@lehins lehins merged commit ea50a9b into lehins:master Jun 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants