Detect UP/DOWN trend direction in financial line-chart screenshots using computer vision.
Project description
๐ chart-direction
Detect the trend direction of a financial line-chart screenshot โ in one line of Python.
Preview
Web UI โ drag-and-drop a chart screenshot, get an instant UP / DOWN signal with full debug pipeline images.
What it does
chart-direction takes a screenshot of any financial line chart and tells you whether the line at the right-hand end is going UP or DOWN โ no manual cropping, no hardcoded colours, no ML model to install.
from chart_direction import ChartDirectionDetector
detector = ChartDirectionDetector()
print(detector("screenshot.png")) # "UP" ๐
It handles real-world chart challenges:
| Challenge | How it's handled |
|---|---|
| Dotted grid lines | Removed via Hough line detection before component analysis |
| Broken/anti-aliased strokes | Reconnected with morphological gap bridging |
| UI panels with large bounding boxes | Rejected using density scoring โ chart lines are sparse, panels are filled |
| Short visible tail at chart end | 3ร zoom + end-extension band search |
Installation
pip install chart-direction
Requirements: Python โฅ 3.8, opencv-python, numpy
Install from source:
git clone https://github.com/MahyudeenShahid/chart-direction.git
cd chart-direction
pip install -e .
Quick Start
One-liner
from chart_direction import ChartDirectionDetector
detector = ChartDirectionDetector()
print(detector("chart.png")) # "UP" or "DOWN"
Full result dict
result = detector.analyze_with_details("chart.png")
if result["success"]:
print(result["direction"]) # "UP"
print(result["end_dir"]) # +1
print(result["trend_start_x"]) # 312 (pixel x where last trend began)
print(result["roi"]) # ROI(x0=780, y0=40, x1=1024, y1=600, w=244, h=560)
Save debug images
result = detector.analyze_with_details("chart.png", outdir="debug/")
This generates 11 images showing every step of the pipeline:
debug/
โโโ full_edges_raw.png Canny edges on full image
โโโ full_edges_clean.png After removing horizontal grid lines
โโโ full_edges_bridged.png After bridging gaps
โโโ full_component.png Selected chart component
โโโ full_component_dilated.png Dilated for tracing
โโโ full_traced.png Traced path + END marker
โโโ original_with_roi.png Original with red ROI box
โโโ zoom.png 3ร zoomed right-end ROI
โโโ edges.png Edges in zoomed ROI
โโโ traced.png Final trace on zoom + "Direction: UP"
โโโ edges_traced.png Trace on edge image
Command-line interface
chart-direction --image chart.png --outdir debug/
# ๐ Direction: UP
# Debug images โ debug/
How It Works
The pipeline has 10 stages, all tunable via constructor parameters:
Input image
โ
1. Crop vertical margins (removes chart title / footer UI)
โ
2. Canny edge detection (finds all edges)
โ
3. Remove horizontal artifacts (erases grid lines via Hough)
โ
4. Bridge gaps (reconnects dotted/anti-aliased lines)
โ
5. Component selection (density-aware scoring picks the chart line)
โ
6. Trace y(x) + extend end (converts mask โ 1-D function)
โ
7. Build zoomed ROI (frame the last ~28% of the chart)
โ
8. Repeat steps 2-5 on zoom (sub-pixel accuracy at 3ร magnification)
โ
9. Gradient โ smooth โ classify (UP / DOWN / FLAT per pixel)
โ
10. Find last direction change โ "UP" or "DOWN"
The density trick (v14 fix)
The key insight that makes this work on full-screen charts:
density = component_area / (bbox_width ร bbox_height)
- A chart line spanning the whole image:
density โ 0.01 โ 0.05(sparse) - A UI panel filling the screen:
density โ 0.3 โ 1.0(dense)
Only reject a huge component when all three hold:
x_span > 95% W AND y_span > 80% H AND density > 0.18
Configuration
detector = ChartDirectionDetector(
# โโ Edge detection โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
canny_low = 30, # lower Canny threshold
canny_high = 120, # upper Canny threshold
# โโ Horizontal artifact removal โโโโโโโโโโโโโโโโโ
hough_threshold = 40, # Hough votes needed
hough_max_gap = 14, # max gap in line segment
horizontal_slope_max = 0.08, # |dy/dx| < this โ horizontal
# โโ Component selection โโโโโโโโโโโโโโโโโโโโโโโโโ
min_component_area = 160, # ignore tiny blobs
density_threshold = 0.18, # UI panel detector
# โโ End-extension โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
band_half_height = 22, # ยฑ pixel search band
max_end_gap = 18, # stop after this many blank columns
# โโ Direction analysis โโโโโโโโโโโโโโโโโโโโโโโโโโ
slope_threshold = 0.15, # gradient < this โ flat
smooth_win_trace = 9, # smoothing window on y(x)
smooth_win_grad = 7, # smoothing window on dy/dx
# โโ ROI & zoom โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
last_w_frac_graph = 0.28, # analyse last 28% of chart
full_y_margin_frac = 0.02, # crop 2% top & bottom
zoom_factor = 3.0, # 3ร magnification on ROI
)
Tuning tips
| Goal | Change |
|---|---|
| More sensitive to shallow trends | Lower slope_threshold (e.g. 0.08) |
| Charts with thin/faint lines | Lower canny_low (e.g. 15) |
| Analyse a wider end section | Increase last_w_frac_graph (e.g. 0.40) |
| Very high-resolution images | Increase zoom_factor (e.g. 4.0) |
| Noisy images with many components | Increase min_component_area (e.g. 300) |
Documentation
| Doc | Description |
|---|---|
| Quick Start | Installation, basic usage, CLI |
| API Reference | All classes, methods, parameters |
| File Reference | Every file explained โ how it works and how it connects |
| Changelog | Version history |
| Contributing | How to contribute |
Contributing
Contributions are very welcome! Please read CONTRIBUTING.md first.
# Fork โ clone โ create branch
git checkout -b feat/my-feature
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Format
black chart_direction/
ruff check chart_direction/
# Open a PR ๐
License
MIT ยฉ 2026 Mahyudeen Shahid
Made with โค๏ธ and OpenCV
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chart_direction-1.0.0.tar.gz.
File metadata
- Download URL: chart_direction-1.0.0.tar.gz
- Upload date:
- Size: 16.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d185d4a9b4cac35c4780f161cfc6a709c36de8596b7888dbe395624d7c93955
|
|
| MD5 |
632b75f7308743bedbbe18447f158d4c
|
|
| BLAKE2b-256 |
ac185204b4c6e132945c8a3fcdd945d21153c7fc23e07f396e90f076407d2439
|
File details
Details for the file chart_direction-1.0.0-py3-none-any.whl.
File metadata
- Download URL: chart_direction-1.0.0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a091846e172f45f22dfaf2541559c2f27c2fc371f9da05ae853861edef669dad
|
|
| MD5 |
147ebc1ce0eb4ed25d5f8cb3f54b405d
|
|
| BLAKE2b-256 |
bb95fbb43ec59d193258bbf344db2d4183a04cc5904b11ebef450a516ac6a10d
|