Detects stars in a bitmap or JPEG astronomical photograph and estimates their relative distances using apparent colour shift (red/blue) and apparent size. Each star is classified on the Hertzsprung-Russell diagram.
| Factor | Method |
|---|---|
| Colour Shift | (R−B) / (R+G+B) — positive = red-shifted (farther), negative = blue-shifted (closer) |
| Apparent Size | Smaller apparent radius → farther away (inverse relationship) |
| Combined Distance | Weighted blend of both factors, normalised so nearest star = 1.0 |
- Colour-shift proxy – True spectral redshift requires spectroscopy, but in a broadband RGB photograph the dominant colour channel provides a useful proxy. Stars skewed toward red are treated as red-shifted (receding/more distant); those skewed toward blue as blue-shifted (approaching/closer). A shift index is computed as
shift = (R - B) / (R + G + B)ranging from approximately -1 to +1. - Apparent size proxy – Stars that appear larger (higher FWHM) are treated as relatively closer, and point-like sources as more distant, inspired by the inverse-square law.
- Combined relative distance –
D_rel = k₁ · (1 + shift) + k₂ · (1 / apparent_radius), normalised so the nearest detected star is 1.0 and all others are expressed as multiples of that baseline.
Each star is placed on the HR diagram using its estimated colour temperature and relative luminosity:
| Property | Method |
|---|---|
| Spectral Class | Temperature mapped to Morgan-Keenan classes O, B, A, F, G, K, M |
| Relative Luminosity | Estimated from brightness × radius², normalised so median star ≈ 1.0 |
| HR Region | Classified as Main Sequence, Giant, Supergiant, or White Dwarf based on temperature and luminosity thresholds |
pip install -r requirements.txtopencv-python– image loading and processingnumpy– array operationsPillow– image format supportscipy– connected-component labellingtabulate– formatted table output
python star_analyser.py <image_path> [options]# Basic analysis
python star_analyser.py photo.jpg
# Lower brightness threshold to detect fainter stars
python star_analyser.py photo.bmp --min-brightness 100 --verbose
# Export results to CSV and save an annotated image
python star_analyser.py photo.jpg --output results.csv --annotate marked.jpg
# Limit annotations to the 20 brightest stars
python star_analyser.py photo.jpg --annotate marked.jpg --max-annotations 20| Option | Default | Description |
|---|---|---|
--min-brightness |
120 | Brightness threshold for star candidates (0–255). Lower values detect fainter stars. |
--min-area |
3 | Minimum contour area in pixels. Filters out noise. |
--max-area |
5000 | Maximum contour area in pixels. Filters out large non-star objects. |
--output FILE |
— | Write results to a CSV file. |
--annotate FILE |
— | Save an annotated copy of the image with detected stars circled and labelled. |
--max-annotations N |
all | Limit text labels on the annotated image to the N brightest stars. All stars still get circle markers. |
--verbose |
off | Print extra diagnostic information. |
The script prints a table with the following columns for each detected star:
| Column | Description |
|---|---|
| ID | Sequential star identifier |
| Position | Centroid coordinates (x, y) in pixels |
| R, G, B | Mean colour channel intensities |
| Shift | Colour shift index (-1 to +1) |
| Classification | red-shifted, blue-shifted, or neutral |
| ~Temp | Estimated colour temperature in Kelvin |
| Spectral | Morgan-Keenan spectral class (O, B, A, F, G, K, M) |
| Lum (rel) | Relative luminosity (median star ≈ 1.0) |
| HR Region | Hertzsprung-Russell classification (Main Sequence, Giant, Supergiant, White Dwarf) |
| Radius | Apparent radius in pixels |
| Peak | Peak brightness value |
| Rel. Distance | Relative distance (nearest star = 1.0) |
When using --annotate, stars are circled and colour-coded by HR region:
- 🟠 Orange — Supergiants
- 🟡 Gold — Giants
- 🔵 Cyan — White Dwarfs
- 🔴 Red — Red-shifted (Main Sequence)
- 🔵 Blue — Blue-shifted (Main Sequence)
- 🟢 Green — Neutral (Main Sequence)
Each labelled star shows its ID, spectral class, HR region, and relative distance. Use --max-annotations N to limit labels to the N brightest stars (all stars still get circle markers).