Notifications
Clear all

[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

7 Replies

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, I’m 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