CSU2543 · Yogananda School of AI, Computers and Data Sciences · Shoolini University, Solan (H.P.)
A complete practical lab handbook for CSU2543 — Digital Images Processing, covering the eight prescribed experiments end to end. Every experiment ships in three independently-runnable forms — a Jupyter notebook, an interactive Flask web app, and a fully-static client-side build — so the same lab works in Colab, on a server, or as plain HTML files.
Open the lab → · Practical handbook PDF → · Run any experiment in Colab
- Course details
- Experiments
- Three deployment forms
- Print-ready handbook
- Architecture
- Quick start
- Deploy
- API reference
- Tech stack
- Accessibility
- Security
- Acknowledgements
- License
| Course code | CSU2543 |
| Course title | Digital Images Processing |
| Programme | B.Tech. in Computer Science and Engineering, 8th semester |
| Reference text | Gonzalez & Woods, Digital Image Processing, 3rd Ed. |
| University | Shoolini University, Solan, Himachal Pradesh, India |
| School | Yogananda School of AI, Computers and Data Sciences |
| Faculty in-charge | Ms. Ishani Sharma |
| Submitted by | Divya Mohan · Roll No. GF202214698 |
| Academic session | 2025–2026 |
| # | Experiment | Reference | Notebook | Interactive | Static |
|---|---|---|---|---|---|
| 1 | Loading and displaying digital images | G&W Ch 2 | .ipynb | /practical/1 | p1.html |
| 2 | Impact of sampling rate on spatial resolution | G&W Ch 2 | .ipynb | /practical/2 | p2.html |
| 3 | Image negation, subtraction & inversion | G&W Ch 2–3 | .ipynb | /practical/3 | p3.html |
| 4 | Gamma correction & power-law transformations | G&W Ch 3 | .ipynb | /practical/4 | p4.html |
| 5 | Histogram equalization | G&W Ch 3 | .ipynb | /practical/5 | p5.html |
| 6 | Histogram matching & specification | G&W Ch 3 | .ipynb | /practical/6 | p6.html |
| 7 | 2D correlation & convolution | G&W Ch 3 | .ipynb | /practical/7 | p7.html |
| 8 | Spatial filtering — box, median, Laplacian, Sobel | G&W Ch 3 | .ipynb | /practical/8 | p8.html |
Each experiment follows the same handbook structure: Aim → Description / Theory → Code → Output → Analysis / Conclusion — colour-coded on screen and on the printed PDF.
| Form | Where it runs | When to use it | Source |
|---|---|---|---|
| Jupyter notebook | Google Colab or local Jupyter | Auto-grading, lab assignments, deeper code experimentation | Practical_N.ipynb |
| Flask web app | Cloud Run (current production) or any Linux VM | Interactive demos, picker-driven experimentation, server-side OpenCV | app/, Dockerfile |
| Static client-side build | Cloudflare Pages, Vercel, GitHub Pages | Zero-cost hosting, fully offline-capable browser implementation | pages/ |
The static build re-implements every operation client-side using the Canvas API and pure JavaScript — it is independent of the Flask code path.
Press Ctrl/⌘ + P on any page on the live site and you get a Chicago-style, AAA-accessible handbook ready for submission:
- Cover page matching Shoolini's practical-file template (title, programme, Submitted by / to, school, university, location, date)
- Per-practical cover identifier ("Practical 7: 2D Correlation & Convolution") shown when printing an individual practical, suppressed on the consolidated home printout
- Universal pages — Cover → Certificate → Acknowledgement → Index — when printing from
/ - Index with all 8 experiments and
1.*, 2.*, …, 8.*page references - Colour-coded section banners — Aim (blue), Description / Theory (purple), Code (green), Output (orange), Analysis / Conclusion (red); identical palette across notebooks and the web app
- Literal Python code rendered in the Code section (extracted from the notebooks, not the server processors)
- Result figures auto-mirrored under the Output section via a
beforeprintJS hook so every visible figure ends up in the printout - 2"×2" QR code on each practical's cover encoding the canonical page URL — works behind Cloudflare via Werkzeug
ProxyFix - 2"×2" centred dmj.one watermark at 22% opacity on every content page (suppressed on cover via opaque background + z-index)
- Per-practical page numbering as
N.1, N.2, …using CSS named-page contexts; cover unnumbered - 1-inch margins all sides, justified text, Times New Roman 12pt, JetBrains Mono code blocks
Cloudflare (custom domain dip.dmj.one)
│
▼
Google Cloud Run · asia-south1
dip-practical (revision …008-k2t)
│
▼
┌───────────────────────┴────────────────────────┐
│ │
Flask + Werkzeug ProxyFix precompute.py result cache
Gunicorn 2 workers × 8 threads (32 JSON figures baked into image)
│ │
├────── / Cover · Certificate · Acknowledgement · Index
├────── /practical/<num> Per-practical interactive page + cover QR
├────── /api/p<n>/... POST endpoints, on-demand matplotlib renders
└────── /static/cache/... Pre-computed result figures (instant load)
│
▼
app/processors/p0[1-8]_*.py OpenCV + matplotlib · Agg backend
│
▼
datasets/CH02 · CH03 Auto-downloaded from imageprocessingplace.com
git clone https://github.com/divyamohan1993/dip-practical.git
cd dip-practical
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
python run.py
# Open http://localhost:5000Click the Colab badge at the top of any Practical_N.ipynb — it auto-downloads the Gonzalez & Woods dataset and runs end-to-end.
cd pages
python3 setup.py # one-time: download CH02 dataset and convert .tif → .png
python3 -m http.server 8000 # serve over a local HTTP origin
# Open http://localhost:8000gcloud run deploy dip-practical \
--source . \
--region asia-south1 \
--memory 2Gi \
--allow-unauthenticatedThe Dockerfile runs precompute.py at build time so the image ships with all 32 cached result figures — pages render instantly on first hit, and printed PDFs include the figures even on the very first page load.
chmod +x autoconfig.sh && sudo ./autoconfig.shIdempotent script that installs Python, Nginx (with microcache), systemd unit, log rotation, and UFW rules on a fresh Ubuntu 24.04 host. See autoconfig.sh and deploy/nginx-site.conf.
Deploy pages/ as the build output directory — no backend required. Every operation runs in the browser via the Canvas API.
All endpoints live under /api. Practical processors are lazy-loaded on first call. Every route returns JSON with a base64 PNG plot field for the rendered figure.
| Practical | Endpoints |
|---|---|
| Common | GET /api/chapters · GET /api/chapters/<id>/images · GET /api/image/<filename> |
| P1 — Display | POST /api/p1/display · POST /api/p1/histogram · POST /api/p1/multi-display |
| P2 — Sampling | POST /api/p2/downsample · POST /api/p2/downsample-plot · POST /api/p2/upscale-compare |
| P3 — Negation / Subtract | GET /api/p3/pairs · POST /api/p3/negate · POST /api/p3/subtract · POST /api/p3/pipeline |
| P4 — Gamma | POST /api/p4/gamma · POST /api/p4/gamma-series · POST /api/p4/log-transform · GET /api/p4/curves · POST /api/p4/contrast |
| P5 — Equalization | POST /api/p5/original-histogram · POST /api/p5/equalize · POST /api/p5/transfer-function · POST /api/p5/multi-equalize |
| P6 — Matching | POST /api/p6/source-histogram · POST /api/p6/equalize-baseline · POST /api/p6/match · POST /api/p6/multi-target · POST /api/p6/transfer-analysis |
| P7 — Conv / Corr | GET /api/p7/impulse · POST /api/p7/custom · POST /api/p7/image-filter · POST /api/p7/verify |
| P8 — Filtering | POST /api/p8/box · POST /api/p8/median · POST /api/p8/box-vs-median · POST /api/p8/laplacian · POST /api/p8/sobel |
| Health | GET /health |
| Layer | Tools |
|---|---|
| Backend | Flask 3.1, Gunicorn 25, Werkzeug ProxyFix, OpenCV 4.13 (headless), Matplotlib 3.10 (Agg), NumPy 2.4, Pillow 12, qrcode 8 |
| Static client | Vanilla JavaScript, Canvas API, Chart.js 4, Bootstrap 5.3, MathJax 3 |
CSS3 Generated Content for Paged Media (target-counter, named pages, @bottom-center), Jinja2 conditional sections |
|
| Notebooks | Jupyter ipynb (nbformat 4.4), CSS-styled markdown preamble |
| Hosting | Google Cloud Run + Artifact Registry (asia-south1), Cloudflare custom domain, Google Cloud Build |
| Dataset | Gonzalez & Woods 3rd Edition, Chapters 02 + 03 — auto-downloaded from imageprocessingplace.com on first run |
dip-practical/
├── Practical_1.ipynb … Practical_8.ipynb # Colab-ready notebooks (one per experiment)
├── app/ # Flask web app
│ ├── processors/ # OpenCV + matplotlib operations
│ │ ├── common.py # Shared helpers — load_image, fig_to_base64, qr_data_uri
│ │ └── p0[1-8]_*.py # Per-practical processors
│ ├── routes/ # Flask blueprints — pages.py, api.py
│ ├── templates/ # Jinja2 templates
│ │ ├── base.html # Shared shell with print stylesheet, watermark, cover
│ │ └── practicals/p0[1-8].html # One template per practical
│ └── static/ # CSS, JS, pre-computed cache JSONs (built into image)
├── pages/ # Fully-static Cloudflare-Pages build
│ ├── p[1-8].html # Standalone HTML per practical
│ ├── js/dip.js # Pure-JS image-processing kernel
│ └── data/ # Pre-converted PNG dataset + manifest.json
├── deploy/nginx-site.conf # Production nginx config (microcache + reverse proxy)
├── Dockerfile # Cloud Run image — runs precompute.py at build time
├── gunicorn.cloudrun.py # 0.0.0.0:$PORT bind for Cloud Run
├── gunicorn.conf.py # 127.0.0.1:8000 + file logging for the VM deploy
├── autoconfig.sh # One-command provision of an Ubuntu 24.04 VM
├── precompute.py # Bakes every default result into /static/cache as JSON
├── format_practicals.py # Applies the colour-coded section format to all 8 notebooks
├── format_templates.py # Adds print-only section banners to all 8 web templates
└── format_print_codeoutput.py # Embeds literal Python + Output containers in templates
The lab targets WCAG 2.2 AAA compliance from line one:
- 7:1 minimum contrast ratio on all text
- 44×44 px minimum target size (matches WCAG 2.2 SC 2.5.8)
- Explicit ARIA labels and
aria-livetoast announcements - Full keyboard navigation; visible focus rings; skip-to-content link
- Honours
prefers-reduced-motion,prefers-color-scheme,forced-colors - Captions for every figure and image in print mode
- All HTTP requests served over HTTPS via Cloudflare; HSTS preloaded
Content-Security-Policy,X-Content-Type-Options, andReferrer-Policyheaders set indeploy/nginx-site.conf- Werkzeug
ProxyFixmiddleware honoursX-Forwarded-*only from the Cloud Run / Cloudflare hop - Dependency pins in
requirements.txtresolve every Dependabot advisory open on the default branch - No secrets in the repo; the only outbound network call is the on-demand dataset download from imageprocessingplace.com (cached locally)
To report a vulnerability, please see SECURITY.md.
This lab is built as part of the coursework for CSU2543 — Digital Images Processing at Shoolini University, under the supervision of Ms. Ishani Sharma, Faculty In-charge, Yogananda School of AI, Computers and Data Sciences.
Reference dataset: Gonzalez & Woods, Digital Image Processing, 3rd Edition — original images courtesy of imageprocessingplace.com.
Distributed under the MIT License. The Gonzalez & Woods dataset is the property of its respective copyright holders and is auto-downloaded for educational use only.
CSU2543 · Digital Images Processing · Built with care by Divya Mohan (GF202214698) under Ms. Ishani Sharma at Shoolini University.