Help me speed up this function?

Thread Solved

Join Date: Feb 2007
Posts: 1,603
Reputation: scru has a spectacular aura about scru has a spectacular aura about 
Solved Threads: 130
Featured Poster
scru's Avatar
scru scru is offline Offline
Posting Virtuoso

Help me speed up this function?

 
0
  #1
Feb 4th, 2009
This function is supposed to take an integer that contains an rgb value, extract the value of each channel, and then return that calculated luminance of the pixel.

As it stands, the performance of this function is not fast enough. Looking at it, I can't think of anything else that I can do to speed it up.

Also, I was thinking if there's an algorithm to calculate the luminance straight from the integer instead of converting to rgb first, and whether that would be faster.

Anyway, here it is:
  1. def luminance(pixel):
  2. """Calculate and return the luminance of a pixel."""
  3. r = pixel & 255
  4. g = (pixel & (255 << 8)) >> 8
  5. b = pixel >> 16
  6.  
  7. return 0.299 * r + 0.587 * g + 0.114 * b

Edit: What ever improvements you may have, however little they are, don't hesitate to suggest them. This function is called hundreds of thousands (sometimes even millions) of times by the script.
Last edited by scru; Feb 4th, 2009 at 3:49 pm.
Reply With Quote Quick reply to this message  
Join Date: Jun 2005
Posts: 2,039
Reputation: Rashakil Fol is just really nice Rashakil Fol is just really nice Rashakil Fol is just really nice Rashakil Fol is just really nice 
Solved Threads: 139
Team Colleague
Rashakil Fol's Avatar
Rashakil Fol Rashakil Fol is offline Offline
Super Senior Demiposter

Re: Help me speed up this function?

 
0
  #2
Feb 4th, 2009
Write it in C.

Edit:
Well, for starters,
  1. g = (pixel >> 8) & 255;
Last edited by Rashakil Fol; Feb 4th, 2009 at 4:18 pm.
Reply With Quote Quick reply to this message  
Join Date: Jun 2005
Posts: 2,039
Reputation: Rashakil Fol is just really nice Rashakil Fol is just really nice Rashakil Fol is just really nice Rashakil Fol is just really nice 
Solved Threads: 139
Team Colleague
Rashakil Fol's Avatar
Rashakil Fol Rashakil Fol is offline Offline
Super Senior Demiposter

Re: Help me speed up this function?

 
1
  #3
Feb 4th, 2009
It's not necessary to right-shift a value immediately before you multiply it by a constant. So:

  1. def luminance(pixel):
  2. """Calculate and return the luminance of a pixel."""
  3.  
  4. return 0.299 * (pixel & 0xFF) + 0.002293 * (pixel & 0xFF00) + .00000174 * (pixel & 0xFF0000)

I assume removing the doc comment doesn't help, but maybe you shouldn't.
Last edited by Rashakil Fol; Feb 4th, 2009 at 4:24 pm.
Reply With Quote Quick reply to this message  
Join Date: Jun 2005
Posts: 2,039
Reputation: Rashakil Fol is just really nice Rashakil Fol is just really nice Rashakil Fol is just really nice Rashakil Fol is just really nice 
Solved Threads: 139
Team Colleague
Rashakil Fol's Avatar
Rashakil Fol Rashakil Fol is offline Offline
Super Senior Demiposter

Re: Help me speed up this function?

 
0
  #4
Feb 4th, 2009
Also, there's the option of inlining the code, so that you don't incur the cost of a function call (which seems to me like it would be a problem in Python).

No seriously, write this performance-intensive part in C.
Reply With Quote Quick reply to this message  
Join Date: Feb 2007
Posts: 1,603
Reputation: scru has a spectacular aura about scru has a spectacular aura about 
Solved Threads: 130
Featured Poster
scru's Avatar
scru scru is offline Offline
Posting Virtuoso

Re: Help me speed up this function?

 
1
  #5
Feb 4th, 2009
I don't want to write it in C because the script is to be used to demonstrate how something can be done in Python.

I really only want the fastest speed that python can offer (as I said, it's just for demonstration), so if this is as fast as it gets, I will be happy to settle.
Last edited by scru; Feb 4th, 2009 at 5:23 pm.
Reply With Quote Quick reply to this message  
Join Date: Oct 2004
Posts: 4,006
Reputation: vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice 
Solved Threads: 928
Moderator
vegaseat's Avatar
vegaseat vegaseat is online now Online
DaniWeb's Hypocrite

Re: Help me speed up this function?

 
0
  #6
Feb 4th, 2009
Rashakil Fol's approach shaves off a few precious fractional microseconds ...
  1. # calculate the luminance of a color pixel
  2. # (psyco does not help to improve speed)
  3.  
  4. def luminance1(pixel):
  5. """calculate and return the luminance of a denary pixel value"""
  6. r = pixel & 255
  7. g = (pixel & (255 << 8)) >> 8
  8. b = pixel >> 16
  9. return 0.299 * r + 0.587 * g + 0.114 * b
  10.  
  11. def luminance2(pixel):
  12. """calculate and return the luminance of a denary pixel value"""
  13. r = pixel & 255
  14. g = (pixel >> 8) & 255
  15. b = pixel >> 16
  16. return 0.299 * r + 0.587 * g + 0.114 * b
  17.  
  18. def luminance3(pix):
  19. """calculate and return the luminance of a denary pixel value"""
  20. return 0.299*(pix&255)+0.587*((pix>>8)&255)+0.114*(pix>>16)
  21.  
  22. def luminance4(pix):
  23. """calculate and return the luminance of a denary pixel value"""
  24. return 0.299*(pix&0xFF)+0.00229297*(pix&0xFF00)+0.0000017395*(pix&0xFF0000)
  25.  
  26.  
  27. color = "0xFF6734"
  28. pix = int(color, 16)
  29. lum1 = luminance1(pix)
  30. print( "1) color pixel = %d (%X) has luminance %f" % (pix, pix, lum1) )
  31. lum2 = luminance2(pix)
  32. print( "2) color pixel = %d (%X) has luminance %f" % (pix, pix, lum2) )
  33. lum3 = luminance3(pix)
  34. print( "3) color pixel = %d (%X) has luminance %f" % (pix, pix, lum3) )
  35. lum4 = luminance4(pix)
  36. print( "4) color pixel = %d (%X) has luminance %f" % (pix, pix, lum4) )
  37.  
  38. print('-'*60)
  39.  
  40. import timeit
  41.  
  42. def use_timeit(stmt, setup, passes=1000000):
  43. """
  44. use module timeit to time a statement stmt
  45. (this can be a function call too)
  46. setup gives information where too find variables/functions
  47. for time consuming functions use fewer passes to save time
  48. for instance -->
  49. stmt='myfunction(x)'
  50. setup='from __main__ import myfunction, x'
  51. """
  52. t = timeit.Timer(stmt=stmt, setup=setup)
  53. # doing 10 passes * 100000 gives the time in microseconds/pass
  54. elapsed = (1000000//passes * t.timeit(number=passes))
  55. print( "Function '%s' takes %0.3f micro-seconds/pass" % (stmt, elapsed) )
  56.  
  57. stmt = 'luminance1(pix)'
  58. setup = 'from __main__ import luminance1, pix'
  59. use_timeit(stmt, setup, passes=1000000)
  60.  
  61. stmt = 'luminance2(pix)'
  62. setup = 'from __main__ import luminance2, pix'
  63. use_timeit(stmt, setup, passes=1000000)
  64.  
  65. stmt = 'luminance3(pix)'
  66. setup = 'from __main__ import luminance3, pix'
  67. use_timeit(stmt, setup, passes=1000000)
  68.  
  69. stmt = 'luminance4(pix)'
  70. setup = 'from __main__ import luminance4, pix'
  71. use_timeit(stmt, setup, passes=1000000)
  72.  
  73. """
  74. typical result on my computer -->
  75. 1) color pixel = 16738100 (FF6734) has luminance 105.079000
  76. 2) color pixel = 16738100 (FF6734) has luminance 105.079000
  77. 3) color pixel = 16738100 (FF6734) has luminance 105.079000
  78. 4) color pixel = 16738100 (FF6734) has luminance 105.079000
  79. ------------------------------------------------------------
  80. Function 'luminance1(pix)' takes 1.647 micro-seconds/pass
  81. Function 'luminance2(pix)' takes 1.613 micro-seconds/pass
  82. Function 'luminance3(pix)' takes 1.600 micro-seconds/pass
  83. Function 'luminance4(pix)' takes 1.317 micro-seconds/pass
  84. """
May 'the Google' be with you!
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the Python Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC