Re: Fun with sobel - Neon Effect - Thick Edge Detection
Posted: 2009-08-27T19:55:27-07:00
see radon transform at viewtopic.php?f=2&t=14532&p=50617#p50617
Use https://github.com/ImageMagick/ImageMagick/discussions instead.
https://imagemagick.com/discourse-server/
https://imagemagick.com/discourse-server/viewtopic.php?t=14491
Code: Select all
convert rectrot2.png -resize 50x50! -colorspace gray ^
( -clone 0 -bias 50% -convolve "-0.125,0,0.125, -0.25,0,0.25, -0.125,0,0.125" ) ^
( -clone 0 -bias 50% -convolve "-0.125,-0.25,-0.125, 0,0,0, 0.125,0.25,0.125" ) ^
-delete 0 ^
-fx "uu=(u-0.5)*2;vv=(v-0.5)*2; hypot(uu,vv)>0.05 ? atan2(vv,uu) /pi/2+0.5 : 0" -write THETA.png ^
-fx "uu=(u-0.5)*pi*2; u>0 ? ((i/w)*cos(uu) + (j/h)*sin(uu)) /sqrt(2)/2+0.5 : 0" RHO.png
scatter THETA.png RHO.png HOUGH.png
I agree and that was my first thought alsoThis should be equivalent to the oriented hough transform described in the paper by Zhang and He. The classic hough transform would require a lot more effort to compute this way (repeat the whole process N times, for all possible theta values, then add the resulting 2d plots).
Yes, that is why I was not sure it would help other than give you an idea about how to produce a 2D histogram. But it needs extending so that it is grayscale and not binary.The binary nature of the scatter script makes this difficult
Code: Select all
#!/usr/bin/python
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
################################################################
#
# This is a standalone program.
# it requires
# - python 2.6+ ( 2.5 or 2.4 works probably too)
# - openCV with PythonInterface installed
#
################################################################
#
# USAGE: hough2.py SOURCEFILE [OUTFILE]
#
import sys
from math import sin,cos,sqrt,degrees,radians,atan2,hypot,pi
from opencv.cv import *
from opencv.highgui import *
# ORIENTED HOUGH TRANSFORM
def orientedHoughTransform(edges,sobelX,sobelY,accumulator):
maxtheta = pi
maxrho = hypot(edges.width, edges.height)
maxacc = -1000000
for x in range(0,edges.width):
for y in range(0,edges.height):
#print x,y, edges.width,edges.height
if edges[y,x]>0:
theta = atan2(sobelY[y,x],sobelX[y,x])
rho = x*cos(theta) + y*sin(theta)
t=int(round ((theta/maxtheta/2 +0.5) * (accumulator.width-1) ))
r=int(round ((rho /maxrho /2 +0.5) * (accumulator.height-1)))
acc=accumulator[r,t]
acc+=1
accumulator[r,t]=acc
if acc>maxacc: maxacc=acc
#print theta,sobelY[y,x],sobelX[y,x]
cvConvertScale(accumulator,accumulator,100000/maxacc)
# ORIENTED HOUGH TRANSFORM WITH MODIFICATIONS
def orientedHoughTransform2(edges,sobelX,sobelY,accumulator):
maxtheta = pi
maxrho = hypot(edges.width, edges.height)
maxacc = -1000000
for x in range(0,edges.width):
for y in range(0,edges.height):
#print x,y, edges.width,edges.height
if edges[y,x]>0:
theta2 = atan2(sobelY[y,x],sobelX[y,x])
for ii in range(-180,179):
theta= radians(ii)
rho = x*cos(theta) + y*sin(theta)
t=int( ((theta/maxtheta/2 +0.5) * (accumulator.width-1) ))
r=int( ((rho /maxrho /2 +0.5) * (accumulator.height-1)))
acc=accumulator[r,t]
if abs(theta-theta2)<radians(10): acc+=1
else: acc-=1
accumulator[r,t]=acc
if acc>maxacc: maxacc=acc
#print theta,sobelY[y,x],sobelX[y,x]
print maxacc
cvConvertScale(accumulator,accumulator,32767/maxacc)
if __name__ == "__main__":
if len(sys.argv)>1:
srcfile = sys.argv[1]
srcImg=cvLoadImage(srcfile, 0);
if not srcImg:
print "Error opening image %s" % srcfile
sys.exit(-1)
edgeImg = cvCreateImage( cvGetSize(srcImg), 8, 1 );
cvCanny( srcImg, edgeImg, 200, 100, 3 );
sobelXImg = cvCreateImage( cvGetSize(srcImg), IPL_DEPTH_16S, 1 );
cvSobel( srcImg, sobelXImg, 1, 0, 3 );
sobelYImg = cvCreateImage( cvGetSize(srcImg), IPL_DEPTH_16S, 1 );
cvSobel( srcImg, sobelYImg, 0, 1, 3 );
accumulatorImg = cvCreateImage( cvSize(360,360), IPL_DEPTH_16S, 1 );
cvZero( accumulatorImg );
orientedHoughTransform(edgeImg, sobelXImg, sobelYImg, accumulatorImg)
if len(sys.argv)>2:
outfile = sys.argv[2]
cvSaveImage(outfile,accumulatorImg)
else:
cvNamedWindow( "hough", 1 );
cvShowImage( "hough", accumulatorImg );
cvWaitKey(0);
cvShowImage( "hough", edgeImg );
cvWaitKey(0);
# cvShowImage( "hough", sobelYImg );
# cvWaitKey(0);
Not sure actually, it might be the middle of the book, or one of the other lines. I still have to finish the code that finds the local maxima in hough space and converts them back into lines.fmw42 wrote:why 5 (not 4) bright spots? Is that due to the open pages on the left side of the book?
I never worked with AWK, but it seems like a bad match. Why AWK?I wonder if something like this could be done with AWK (Anthony?)
I never figured out what the advantages and disadvantages of the radon or the hough transform are for this sort of problem. Are there fundamental differences of the results (for the classical cases)?Just for curiosity and comparison, I tried the ImageJ radon transform on the original and an edge image (both cropped to square dimensions required by the radon plugin)
interestingly, the oriented hough transform does not work at all if it only has this sort of edge image as input.simple edge:
convert pic4nb.png -monochrome -median 2 -edge 1 pic4nb_mono_med2_edge1.png
Just learning a bit of it and finding that for what it can do, it can do it so much faster than bash scripting with while or for loops.I never worked with AWK, but it seems like a bad match. Why AWK?
Not totally sure either. Seemed to be a bit less noise sensitive from what i have read. Also I knew that Magick had implemented some version of it and thought it might be something that could be extracted for direct use in IM easily (but not the case).I never figured out what the advantages and disadvantages of the radon or the hough transform are for this sort of problem. Are there fundamental differences of the results (for the classical cases)?
Hough seems to be faster to calculate, if I only loop over the edges. and easier to thinker with. But that might be because the integrals confuse me.
I would not necessarily expect it to work as you are doing and edge extraction on an edge image. Perhaps better to try from the binary image I made before extracting the edge. Here it is:interestingly, the oriented hough transform does not work at all if it only has this sort of edge image as input.
To calculate precise gradient orientation, The sobel results of the original images are needed
If I run sobel over this edge image, the gradient varies to much to give any meaningful result.
Not much better actually. As far as I can tell the problem is mainly the binary nature of the image. With a 3x3 sobel over binary data, there are only 8 possible values, so the hough space is strongly quantized in the theta direction.I would not necessarily expect it to work as you are doing and edge extraction on an edge image. Perhaps better to try from the binary image I made before extracting the edge. Here it is:
I am a big fan of python, but it is partialy a matter of taste. I think all of them are better suited than bash for complex algorithms.What are the pros and cons of python vs perl? And where does Ruby fit in all this?
Had not considered that. I don't understand why it is quantized to 8 directions only if you are using arctan2(DY,DX) for getting theta. Should you not get the actual angle of the lines? I need to think on this more. Nevertheless, why are you getting doubling of the dots? Is that because each opposite side is at a different distance from the origin.Not much better actually. As far as I can tell the problem is mainly the binary nature of the image. With a 3x3 sobel over binary data, there are only 8 possible values, so the hough space is strongly quantized in the theta direction.
with binary data the 3x3 sobelX and the sobelY can have any integer value from -4 to +4, so atan2(sobelY,sobelX) has x<8^2 possible values? not sure about that.fmw42 wrote: Had not considered that. I don't understand why it is quantized to 8 directions only if you are using arctan2(DY,DX) for getting theta. Should you not get the actual angle of the lines? I need to think on this more.
Depends on what you mean.Nevertheless, why are you getting doubling of the dots? Is that because each opposite side is at a different distance from the origin.
So at least this shows the difference between the radon and the hough transform. In the radon transform, one got 4 dots. You get 8 in your Hough.
I know perl myself, I know it well enough that I have written CPAN modules for it. Specifically to do vector mathematics ("VectorReal" module) including the use of 'x' and '.' for cross and dot products, and tie it into another module "MatrixReal". As well as interupted multi-tasking IO handlers!fmw42 wrote:Thanks for your experimentation and for your recommendation about Python. Guess I need to buy and read another book.
Shells are a tool, and we are its carpenters.
Sometimes we need a hammer and sometimes a screwdriver. --- John Navarra