[Closed] Sort Pixels Order?
I have created a series of point out of tracing the white pixels on an image(see LeafPoints.jpg) and want to connect them, the problem is that the pixels are created as the image is read. But as you can see on the image that is not the way it supposes to be.
Is there a way to sort the pixels correctly so I could create a spline out of the traced image?
-- collect the points
Puntos = $Point* as array
-- create the curve
Curva = splineShape()
Curva_index = addNewSpline Curva
for i = 1 to Puntos.count do
(
addKnot Curva Curva_index #corner #line Puntos[i].pos
)
close Curva 1
updateShape Curva
Thanks for any tips
Guillermo M leal Llaguno
Do you mean that the problem is that you determine the coordinates in the points array from pixel 1×1 (left-top) to the final pixel in the right-bottom of the source picture?
And you want it to sort of follow the shape in the image?
If so, you could write a loop that ‘crawls’ through the image from a certain starting point. You could for example have it look for the first white pixel in the near (1px) surrounding, and if that’s found, repeat the loop with the newfound white pixel as the center.
I have attached now the max8 file(LeafPoints.zip ) with the points and the result after running the script .
as you can see the spline its created in the order the pixels were read, but i want the spline to follow the points.
is there a way to arrange the array?
thanks,
Guillermo Leal.
How did you read the pixel data?
Just with a loop going through each line of pixels and storing the coordinate of a white pixel?
And could I see the source image perhaps?
Pjanssen,
yes i went trough the pixels and where there is a white pixel i put a point in it.
here is the code:
-- Puts Point in white pixels from image
tempImage = openbitmap "O:\\Gtools\\Clip\\hoja_S2.jpg"
pixel_line
PixelPoint = #()
progressstart "Generating Objects..."
for h = 1 to tempImage.height do
(
pixel_line = getpixels tempImage [0,(h-1)] tempImage.width
if not progressupdate (h as float /tempImage.height *100) then exit
for w = 1 to tempImage.width do
(
PixelPoint = (pixel_line[w].r+pixel_line[w].g+pixel_line[w].b)/3
if PixelPoint == 255 then
(
new_object = Point ()
new_object.centermarker = true
new_object.axistripod = false
new_object.cross = false
new_object.box = False
new_object.pos = [w, - h, 0]
new_object.name = uniquename "Point"
)
)--end w loop
)--end h loop
progressend ()
but i see that there is much more work to do to achive that, see this link.
http://www.cs.mcgill.ca/~aghnei/index.html
has anyone have any pointers on how to loop trough the picels like in does examples.?
thanks,
Guillermo Leal
Select the bottom left point you want to start with and write a script that finds the closest neighbor based on direction.
The first point will look through all other points and will have no other option than to go to the closest point above it. Record the vector defined by the two points and remove both from the list of points to process.
Then repeat by looking from the second point and looking for the closest point and the least angle defined by the possible neighbor and the previous vector. So if there are two points that are at the same distance, pick the one that defines the vector closest to the previous vector.
Repeat the above until there are no points left to scan for. Chances are you will have collected all points along the curve they define, since otherwise they are collected according to their creation order.
Bobo,
Great explanation, it make sense. But unfortunately I havent been able to figure out how to do transfer your explanation into maxscript, Im relative new to maxscript.
I will keep trying to find a solution.
Thanks a lot, at list now I know the way to find it.
Appreciated.
Guillermo Leal
Bobo,
Please take a look at this code, I think i´m able to find the first point but if I try to put that code inside another loop to get all points I get array index out of bounds: 8
Cloud you point out the problem?
Originalpoints = $point* as array
SortedPoints = #() -- New Sorted Points
restOfPoints = for i in Originalpoints collect i -- makes a copy of the original array
deleteItem restOfPoints 1
CurrentPoint = Originalpoints[1]
PointsAngle = #()
PointDistance =#()
AngleIndex
DistanceIndex
FoundIndex
-- for g in Originalpoints do
(
restOfPoints = for i in restOfPoints where isValidNode i collect i -- updates the array
if restOfPoints.count >= 1 then -- checks to see if the array its not empty
for z = 1 to restOfPoints.count do -- loop troough the pixels to get the first point
(
-- get the Angle
getAngle = acos (dot (normalize CurrentPoint.pos) (normalize restOfPoints[z].pos))
append PointsAngle getAngle -- adds angles to PointsAngle array
-- get the Distance
getDistance = distance CurrentPoint.pos restOfPoints[z].pos
append PointDistance getDistance -- adds angles to PointDistance array
-- Print info
format "Name:% , Angle:% , Distance:%
" restOfPoints[z].name PointsAngle[z] PointDistance[z]
)
---- Angle ----
-- finds the smallest angle in the PointsAngle array
SmallestAngle = amin PointsAngle
-- looks at the PointsAngle array for the smallest angle we just got and returns the index
AngleIndex = finditem PointsAngle SmallestAngle
-- we use the previus index to get the point from the restOfPoints array
TempPointAngle = restOfPoints[AngleIndex]
---- Distance ---
-- finds the smallest Distance in the PointDistance array
SmallestDistance = amin PointDistance
-- looks at the PointDistance array for the smallest Distance we just got and returns the index
DistanceIndex = finditem PointDistance SmallestDistance
-- we use the previus index to get the point from the restOfPoints array
TempPointDistance = restOfPoints[DistanceIndex]
----- checks if angle is the lowest if not th shoretes distance so we find the index to add to sorted
if PointsAngle[AngleIndex] <= amin PointsAngle then FoundIndex = AngleIndex
else if PointDistance[DistanceIndex] <= amin PointDistance do FoundIndex = DistanceIndex
-- finds the Point in the SortedPoints array
TempFound = restOfPoints[FoundIndex]
-- append the FoundPoint to the SortedPoints array
append SortedPoints TempFound
-- assing the second point to the CurrentPoint variable so it starts from there
CurrentPoint = TempFound
-- deletes the point we have alreadey got from the restOfPoints array
deleteItem restOfPoints FoundIndex
-- print info
format "
AngleIndex:%
DistanceIndex:%
" AngleIndex DistanceIndex
format "
Originalpoints:%
SortedPoints:%
RestOfPoints:%
" Originalpoints.count SortedPoints.count restOfPoints.count
)
Thanks again
Guillermo Leal