#!/usr/bin/env python # coding: utf-8 # # Siemens Star # # The [Siemens Star](https://en.wikipedia.org/wiki/Siemens_star) is a radial starburst pattern commonly used to adjust internal focus settings in camera lens and for measuring camera resolution. This notebook produces a Siemens Star test chart in the form in [Scalable Vector Graphics (svg)[(https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) that can be rendered by most modern web browsers. The idea for this notebook was motivated by this [post](http://www.dpreview.com/forums/post/57422062) on a forum at [Digital Photography Review (DPReview)](http://www.dpreview.com/). # # ## References # # * [Digital Camera Resolution Measurement Using Sinusoidal Siemens Stars](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.470.2385&rep=rep1&type=pdf) # * [Wikipedia: Siemens star](https://en.wikipedia.org/wiki/Siemens_star) # * [Image Engineering: Resolution measurement with siemens stars](https://github.com/jckantor/Siemens-Star) # * [A/D Photography: Resolution Test Chart – Siemens star](https://claclaclack.wordpress.com/2015/05/17/resolution/) # * [Lens Rentals: Setting Up an Optical Testing Station](https://www.lensrentals.com/blog/2014/02/setting-up-an-optical-testing-station/) # * [Imatest: Star Chart](http://www.imatest.com/docs/starchart/) # # # ## Usage # # This is a [Jupyter notebook](http://jupyter.org/) containing Python functions. An executable version of this notebook is available from the [http://mybinder.org/](http://mybinder.org/) by clicking on the following button. There may be a longish pause as the notebook loads. # # [![Binder](http://mybinder.org/badge.svg)](http://mybinder.org/repo/jckantor/Siemens-Star) # # To use the notebook after it has been loaded in an executable environment: # # 1. First run the code in the following cell. Do this by clicking in the cell to highlight it, then entering 'shift-return' from the keyboard, or clicking on the run button in the toolbar menu (looks like >|), or the 'Cell>Run Cells' menu item. # 2. Execute the second cell below to create the desired chart interactively. The controls adjust the colors and number of spokes displayed in the chart. # ## Imports # In[10]: get_ipython().system('pip install svglib') # ## Function Definitions # # The following cell defines functions that create SVG markup. Run this cell first! # In[11]: from math import pi, sin, cos, sqrt # page width page_width = 900 # xrite passport rgb color table # https://xritephoto.com/ph_product_overview.aspx?ID=820&Action=support&SupportID=5159 rgb = [ [115, 82, 68], # 1. dark skin [194,150,130], # 2. light skin [ 98,122,157], # 3. blue sky [ 87,108, 67], # 4. folliage [133,128,177], # 5. blue flower [103,189,170], # 6. bluish green [214,126, 44], # 7. orange [ 80, 91,166], # 8. purplish blue [193, 90, 99], # 9. moderate red [ 94, 60,108], # 10. purple [157,188, 64], # 11. yellow green [224,163, 46], # 12. orange yellow [ 56, 61,150], # 13. blue [ 70,148, 73], # 14. green [175, 54, 60], # 15. red [231,199, 31], # 16. yellow [187, 86,149], # 17. magenta [ 8,133,161], # 18. cyan [243,243,242], # 19. white (0.05*) [200,200,200], # 20. neutral 8 (0.23*) [160,160,160], # 21. neutral 6.5 (0.44*) [122,122,121], # 22. neutral 5 (0.70*) [ 85, 85, 85], # 23. neutral 3.5 (1.05*) [ 52, 52, 52], # 24. black (1.50*) ] def star(xc, yc, radius, cycles=72, colors=['black', 'white']): """Return an svg string containing of polygons in the form of a star.""" phi = pi/cycles/len(colors) xy = [xc, yc, xc - radius*sin(phi), yc + radius*cos(phi), xc + radius*sin(phi), yc + radius*cos(phi)] fmt = '\n'.format(xc, yc) return ''.join([fmt.format(colors[k], 360.0*(n + float(k)/len(colors))/cycles) for n in range(0, int(cycles)) for k in range(0, len(colors))]) def lphcircles(xc, yc, radius, cycles, colors, bb_height): lph = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000] r = [bb_height*cycles*len(colors)/(2*pi*lph) for lph in lph] fmt = '\n' +\ '{5:4.0f}' return '\n'.join([fmt.format(xc, yc, r, xc+r*cos(13*pi/8), yc + r*sin(13*pi/8), lph) for (lph,r) in zip(lph,r) if 10 < r < radius]) + '\n' def colorchecker(bw, bh): return ''.join(['1)), bh*(7+row)) + ' style="fill:rgb({0},{1},{2});stroke-width:2;stroke:black"/>\n'.format(*rgb[row + 6*col]) for col in range(0,4) for row in range (0,6)]) def SiemensStar(cycles=144, aspect=4/3, colors=['black','white'], colorcheck='True', cstars='True', lph='True'): bb_width = page_width bb_height = bb_width/aspect r = bb_height*min(0.5, (sqrt(1+aspect**2))/4) svg = '\n'.format(bb_width, bb_height) svg += star(bb_width/2, bb_height/2, r, cycles, colors) svg += lphcircles(0.5*bb_width, 0.5*bb_height, r, cycles, colors, bb_height) if lph else '' if cstars: for x,y in [(x,y) for x in (0, bb_width) for y in (0, bb_height)]: svg += star(x, y, r, cycles, colors) svg += lphcircles(x, y, r, cycles, colors, bb_height) if lph else '' svg += colorchecker(0.05*bb_width, 0.05*bb_height) if colorcheck else '' return svg + '' # ## Manually Create and Display the Siemens Star # # The following cell creates a simple resolution chart consisting of a central Siemens Star and additional elements. The central star consists of alternating radial spokes of color from a specified list `colors`. If omitted, the default is black and white. The list may contain two or more colors. The list of colors is repeated a number of times as determined by the parameter `cycles`. # # A list of svg commands is generated, stored in a file [star.svf](star.svg), and displayed as an inline graphic within the notebook. To download the resulting file, right click on the link and choose the `Save Link As ...` option. # In[14]: from IPython.display import SVG from svglib.svglib import svg2rlg from reportlab.graphics import renderPDF, renderPM svg = SiemensStar(cycles=144, colors = ['blue', 'yellow']) with open('star.svg', 'w') as f: f.write(svg) chart = svg2rlg('star.svg') renderPDF.drawToFile(chart, 'star.pdf') renderPM.drawToFile(chart, 'star.png', fmt='PNG') SVG(svg) # ## Interactively Create and Display Siemens Star # # The following interactive cell creates a simple resolution chart consisting of a central Siemens Star and additional elements. Use the dropdown menus to set the colors of the radial spokes, and the cycles slider to set the number of spokes. # # A list of svg commands is generated and stored in a file [star.html](star.html). To download the resulting file, right click on the link and choose the `Save Link As ...` option. # In[15]: from IPython.display import SVG from ipywidgets import interact, Dropdown, IntSlider, Checkbox from IPython.display import display svg_colors = ['black', 'white', 'red', 'blue', 'green', 'cyan', 'yellow', 'magenta'] def makestar(cycles, aspect, color1, color2, colorcheck, cstars, clines): svg = SiemensStar(cycles, aspect=eval(aspect), colors=[color1,color2], colorcheck=colorcheck, cstars=cstars, lph=clines) display(SVG(svg)) with open('star.html','w') as f: f.write(svg) interact(makestar, cycles = IntSlider(min=12, max=600, value = 144, step=2, description='Color Cycles'), \ aspect = Dropdown(options=['16/9', '3/2', '4/3', '1/1'], value='4/3', description='Aspect Ratio'), \ color1 = Dropdown(options=svg_colors, value='black', description='Color A'), \ color2 = Dropdown(options=svg_colors, value='white', description='Color B'), \ colorcheck = Checkbox(value=True, description='Color Checker'), \ cstars = Checkbox(value=True, description='Corner Stars'), \ clines = Checkbox(value=True, description='LPH Lines')) # In[ ]: