basic course content added, more TODO
175
courses/uoph410-510a_Image-Analysis/setup.md
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
---
|
||||
title: Setting up and Managing Python Environments
|
||||
author: "[Thomas (Tom) C. Gorordo](https://pages.uoregon.edu/tgorordo) - your TA"
|
||||
date: 2024-10-01
|
||||
lang: en
|
||||
...
|
||||
|
||||
To help you get started/possibly avoid at least some tech support/give some advice here's a brief note on Python development environments.
|
||||
|
||||
So, welcome to the zoo that is software configuration!
|
||||
|
||||

|
||||
|
||||
### POSIX Shells and Environments
|
||||
|
||||
It won't come up very often in the course assignments themselves, but for tech support I will generally assume you have access to
|
||||
a [POSIX](https://en.wikipedia.org/wiki/POSIX) compliant shell (command-line) somewhere on your
|
||||
machine. If you're using a Linux or Mac operating system
|
||||
your default shell is likely [`bash`](https://www.gnu.org/software/bash/) or
|
||||
[`zsh`](https://zsh.sourceforge.io/) (or some variant or equivalent thereof accessible through some kind of 'terminal' program), in which case you should be good-to-go.
|
||||
If you're on Windows things may be more complicated -
|
||||
I'm not very up to speed on the current state of [powershell](https://learn.microsoft.com/en-us/powershell/) -
|
||||
but I can recommend looking into the [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/),
|
||||
or [`git-bash`](https://gitforwindows.org/), and/or [CygWin](https://www.cygwin.com/)
|
||||
as ways to get a \*nix-like environment on Windows that I'll be able to help with.
|
||||
|
||||
You may also want an editor like [Visual Studio Code](https://code.visualstudio.com/) or [Spyder](https://www.spyder-ide.org/) - though there are many other valid choices for writing/editing your software for this course.
|
||||
(if you really want to be a shell guru there's always the likes of [neovim](https://neovim.io/);
|
||||
beware the learning curve.)
|
||||
|
||||
You're welcome to set up your technology stack however you'd like, but I can't guarantee I'll be able to debug anything
|
||||
or replicate your environment faithfully when testing your assignments if you deviate too far from modern Linux dev standards and/or common software (I can help with MATLAB or Julia as well as Python - this guide just anticipates Python will be the most common language choice, and that MATLAB is more self-contained/explanatory).
|
||||
|
||||
### Getting and Using Python
|
||||
|
||||
If you don't have it already in some form, you should [download and install Python3](https://www.python.org/downloads/) for your system.
|
||||
You'll also, at a minimum, need to be able to [install packages](https://packaging.python.org/en/latest/tutorials/installing-packages/) (<-- READ THIS LINK if you're at all unsure about what is needed. If you have [`pip`](https://pypi.org/project/pip/) you're good to go with respect to this step).
|
||||
There are some alternative ways of getting/using python (e.g. [`conda`](https://conda.io/projects/conda/en/latest/user-guide/getting-started.html)) -
|
||||
but this note will focus on a pretty generic workflow that should be compatible with essentially *any* up-to-date system-level python installation.
|
||||
|
||||
Depending on your operating system, it might be more appropriate to use a package manager like
|
||||
[`apt`](https://ubuntu.com/server/docs/package-management) (for Debian Linux derivatives like Ubuntu - others for other distros),
|
||||
[homebrew](https://brew.sh/) (for MacOS), or
|
||||
[winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/install?source=recommendations)/[chocolatey](https://chocolatey.org/) (for Windows)
|
||||
instead of downloading and running the installer linked above.
|
||||
Detailed installation instructions will vary a lot by OS, so I won't provide them here - learning how/where to look up system specific ways to do things
|
||||
(and getting familiar with your machine and customizing it to your liking) is an important skill to develop, but you'll mostly have to find favorite resources and methods yourself over time.
|
||||
|
||||
### Dependency Management
|
||||
|
||||
We'll often want our code to depend on various external libraries rather than implement *everything* from scratch ourselves (even though that is often necessary or useful - there are situations we won't want to reinvent the wheel and where a better solution than we could write in a reasonable amount of time/effort exists).
|
||||
The default Python package manager is [`pip`](https://pypi.org/project/pip/) (there are others: [`conda`](https://conda.io/projects/conda/en/latest/user-guide/getting-started.html)
|
||||
is quite popular and handles some of the virtual environment features mentioned below -
|
||||
there's also [`poetry`](https://python-poetry.org/), or I am personally partial to [`uv`](https://docs.astral.sh/uv/).
|
||||
Each work a bit differently, so we'll just cover a barebones python workflow here).
|
||||
|
||||
Python projects often list their 'dependencies' in a `requirements.txt` with contents like:
|
||||
```
|
||||
jupyter
|
||||
numpy
|
||||
matplotlib
|
||||
pandas
|
||||
scipy
|
||||
simpy
|
||||
```
|
||||
|
||||
(some of these are dependencies that will come up in the course - relatively recent versions of each should all work identically well so this list does not specify version numbers [but if you need to lock specific version number down you can do so](https://pip.pypa.io/en/stable/reference/requirements-file-format/)). Given such a file you can install the dependencies for a project into the active environment (usually a venv - see below) via `pip`:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
modules can also be installed explicitly by name:
|
||||
|
||||
```bash
|
||||
pip install numpy scipy
|
||||
```
|
||||
|
||||
(Depending on many OS particulars and settings, you may run into permission issues with these commands - let me know if you need help tracking down how to solve them for your particular setup.)
|
||||
|
||||
If `pip` is only present in your python installation but not exposed to your commandline you may need to use
|
||||
|
||||
```bash
|
||||
python -m pip <remainder of the pip command goes here...>
|
||||
```
|
||||
|
||||
### Virtual Environments
|
||||
It can be important to manage dependencies carefully across projects and over time.
|
||||
For example, suppose you write some code for this course which relies on some specific feature of the current version `numpy1.22` (you might use a particular niche function or rely on a name or shape for some arguments).
|
||||
Two or three years from now the latest `numpy` version might change the name(s) or interface of the feature you used - and your code will stop working!
|
||||
If you want to run your old code you'll need to use an older version of `numpy`, but that may be difficult if you have some newer project that wants to rely on the newer version of the library.
|
||||
While you can ask `pip` to install any version of a library you want at any time (and store a list of required versions in a `requirements.txt`),
|
||||
uninstalling and re-installing different versions of libraries all the time is messy and liable to break something (especially if you need to manage multiple libraries this way).
|
||||
|
||||

|
||||
|
||||
The somewhat standard solution to this kind of problem is a "virtual environment" - rather than rely on our global shell environment to keep track of all our projects somehow (hoping nothing winds up incompatible),
|
||||
we'll manage an independent environment for each project.
|
||||
|
||||
Simple dependency management via a virtual environment can be done entirely with `python` and `pip` using the [`venv`](https://docs.python.org/3/library/venv.html) module - in your shell, in some directory relevant to your project(s) invoke:
|
||||
|
||||
```bash
|
||||
# use the python venv module
|
||||
# to make a new virtual environment stored in the env dir
|
||||
python -m venv env
|
||||
```
|
||||
|
||||
to create a new virtual environment. You can then activate the environment
|
||||
(tell your shell it should use the contained version of python and associated libraries) anytime you want to use it by calling:
|
||||
|
||||
```bash
|
||||
source env/bin/activate # run the activation script located in the env dir
|
||||
```
|
||||
|
||||
Your shell will then use a self-contained version of `python` and any libraries you install with `pip` while in this mode.
|
||||
I recommend using a `venv` of some kind while working on this course -
|
||||
at the very least it will give you a place to experiment without mucking up your global python installation.
|
||||
|
||||
You can leave the virtual environment at any time by calling `exit`.
|
||||
|
||||
### All-together: an example
|
||||
Suppose you want to run a local [`jupyter`](https://jupyter.org/) notebook for yourself - say, to play around a bit and get some ideas ready for an assignment that will require some [`numpy` functions](https://numpy.org/doc/2.1/reference/index.html#reference) and [`matplotlib`](https://matplotlib.org/stable/api/index.html) plotting - but don't yet have anything set up other than your global python installation.
|
||||
Here's a basic workflow using the methods described above:
|
||||
|
||||
1) Set up a working directory along the lines of
|
||||
```bash
|
||||
# make a directory for the course and "change directory" (cd) into it
|
||||
mkdir uoph410-510_image-analysis && cd uoph410-510_image-analysis
|
||||
|
||||
# create a virtual environment for the course and activate it
|
||||
# in the currently open session with your shell (not persistent)
|
||||
python -m venv env && source ./env/bin/activate
|
||||
```
|
||||
|
||||
2) Install the prerequisite packages (in the venv):
|
||||
```bash
|
||||
pip install jupyter numpy matplotlib
|
||||
```
|
||||
It can be convenient to append these to a `requirements.txt` in case you want to send anyone else your code (you shouldn't send a `venv` directory - they're not portable between systems).
|
||||
```bash
|
||||
# create the .txt, ask pip for its requirements,
|
||||
# and "pipe" (>>) the text output from pip into the end of the file
|
||||
touch requirements.txt && pip freeze >> requirements.txt
|
||||
```
|
||||
|
||||
4) Launch `jupyter notebook` & navigate creating a new `.ipynb` in the browser interface.
|
||||
|
||||
5) Voila! Notice that installing a new shell command for interacting with python (`jupyter`) could be managed in the same way as a package providing a library you can use in your code. Both are only enabled locally, and temporarily in the current session without polluting your global environment (you won't have any issues in the future anywhere else on your machine because of any software we just installed). If you have dependency issues, just shut down the notebook (`CTRL-C` in the running terminal) and repeat (2), adding any packages that are throwing various "not found" errors.
|
||||
|
||||
**Note:** `jupyter` is *not* required (nor even really emphasized) in this class - but it can still be a useful tool for quick sanity-checks and pretty-printed tests or document preparation.
|
||||
Generally this course will prefer you to write your code in a more modular fashion than `jupyter`'s [stateful](https://en.wikipedia.org/wiki/State_(computer_science)) environment encourages, i.e. you should structure and think of your code overall as [module/library development](https://learn.scientific-python.org/development/) rather than each assignment a one-off notebook.
|
||||
(Though an optional workflow can be to develop your own module, and import it into a notebook for use with particular values).
|
||||
|
||||
## Additional Considerations
|
||||
|
||||
The guide above covers just a very basic python environment and workflow.
|
||||
For a more featureful development experience you may want to do your own research on (in addition to some of the things scattered above):
|
||||
|
||||
- Linters like [ruff](https://docs.astral.sh/ruff/) or [black](https://black.readthedocs.io/en/stable/), which help you ensure your code is written in a consistent style - to help with readability.
|
||||
|
||||
- Unit testing with [pytest](https://docs.pytest.org/en/8.0.x/) or [`unittest`](https://docs.python.org/3/library/unittest.html) (along with *many* plugins for each/either).
|
||||
In particular, you might find [ipytest](https://jupyter-tutorial.readthedocs.io/en/stable/notebook/testing/ipytest.html) useful for checking that your code is behaving as you expect
|
||||
while you develop your solutions.
|
||||
|
||||
- Type checkers like [mypy](https://www.mypy-lang.org/) or [pyright](https://microsoft.github.io/pyright/#/), while python does not have static typing
|
||||
(the [interpreter](https://en.wikipedia.org/wiki/Interpreter_(computing)) does not know the [type](https://en.wikipedia.org/wiki/Data_type) of an object [before](https://en.wikipedia.org/wiki/Compile_time) [runtime](https://en.wikipedia.org/wiki/Execution_(computing)#Runtime)) - there is some loose tooling available to help you try to structure your code in a type-safe
|
||||
(or at least [duck-typed](https://en.wikipedia.org/wiki/Duck_typing)) - and more likely to be correct - way. These tend to integrate well with testing frameworks mentioned in the last bullet.
|
||||
|
||||
- You may want to manage a version-controlled [git](https://git-scm.com/) repository for your work on the course. Git and [Github](https://github.com/) are ubiquitous in modern software development.
|
||||
While we won't cover their use in this course, privately managing your work with these tools would be excellent practice.
|
||||
|
||||
Good luck, have fun, don't die!
|
||||
|
||||
|
||||
(page [raw pandoc `.md`](setup.md), [github repo](https://github.com/tgorordo/pages.uoregon.edu))
|
||||
BIN
courses/uoph410-510a_Image-Analysis/wk1/AuLait_gray.png
Normal file
|
After Width: | Height: | Size: 835 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk1/AuLait_gray.tif
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk1/Homework0.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk1/Homework1.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk1/best_practices.pdf
Normal file
99
courses/uoph410-510a_Image-Analysis/wk1/s0.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# /// script
|
||||
# requires-python = ">=3.13"
|
||||
# dependencies = [
|
||||
# "marimo>=0.19.7",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
|
||||
return (np,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework0.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def unit_gridcircle_mask(N):
|
||||
ruler = np.arange(-(N + 1.5), (N + 2.5)) / N
|
||||
xx, yy = np.meshgrid(ruler, ruler)
|
||||
mask = np.sqrt(np.square(xx) + np.square(yy)) <= 1
|
||||
return mask
|
||||
|
||||
return (unit_gridcircle_mask,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, unit_gridcircle_mask):
|
||||
def unit_gridcircle_area(N):
|
||||
area = float(np.sum(unit_gridcircle_mask(N), dtype=float) / N**2)
|
||||
return area
|
||||
|
||||
return (unit_gridcircle_area,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, plt, unit_gridcircle_mask):
|
||||
plt.matshow(unit_gridcircle_mask(5), cmap=plt.cm.gray_r)
|
||||
plt.grid(visible=True, color="cyan")
|
||||
plt.xticks(ticks=(np.arange(14) - 0.5))
|
||||
plt.yticks(ticks=(np.arange(14) - 0.5))
|
||||
f = plt.gca()
|
||||
f.axes.xaxis.set_ticklabels([])
|
||||
f.axes.yaxis.set_ticklabels([])
|
||||
plt.show()
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, plt, unit_gridcircle_area):
|
||||
Npts = 100
|
||||
Ns = np.unique(np.floor(np.logspace(np.log10(2), np.log10(2000), Npts)).astype(int))
|
||||
As = list(map(unit_gridcircle_area, Ns))
|
||||
|
||||
plt.figure(figsize=(8,6))
|
||||
plt.semilogx(Ns, As, 'o-', color='steelblue', markerfacecolor='lightblue', markersize=12)
|
||||
xlim = plt.gca().get_xlim()
|
||||
plt.semilogx((xlim[0], xlim[1]), (np.pi, np.pi), ':', linewidth=2.5, color='darkorange')
|
||||
plt.xlabel('N', fontsize=14)
|
||||
plt.ylabel('Area', fontsize=14)
|
||||
plt.xticks(fontsize=12)
|
||||
plt.yticks(fontsize=12)
|
||||
plt.show()
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk1/s0.py.html
Normal file
163
courses/uoph410-510a_Image-Analysis/wk1/s1.py
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
# /// script
|
||||
# requires-python = ">=3.13"
|
||||
# dependencies = [
|
||||
# "marimo>=0.19.7",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
|
||||
return (np,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework1.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Puzzles
|
||||
### a.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt):
|
||||
im_A_png = plt.imread("AuLait_gray.png")
|
||||
im_A_tif = plt.imread("AuLait_gray.tif")
|
||||
return im_A_png, im_A_tif
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_png, plt):
|
||||
plt.imshow(im_A_png, "gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_tif):
|
||||
im_A_tif.shape
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_png, np):
|
||||
np.max(im_A_png)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_tif, plt):
|
||||
plt.imshow(im_A_tif, "gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_tif):
|
||||
im_A_tif.shape
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_tif, np):
|
||||
np.max(im_A_tif)
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## b.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from skimage import io
|
||||
|
||||
return (io,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_png, io):
|
||||
io.imsave("AuLait_gray_png_skout_unscaled.tif", im_A_png)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt):
|
||||
im_A_sk_tif_unscaled = plt.imread("AuLait_gray_png_skout_unscaled.tif")
|
||||
return (im_A_sk_tif_unscaled,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_sk_tif_unscaled):
|
||||
im_A_sk_tif_unscaled.shape
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_sk_tif_unscaled, plt):
|
||||
plt.imshow(im_A_sk_tif_unscaled)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_png, io):
|
||||
io.imsave("AuLait_gray_png_skout_scaledup.tif", im_A_png * 255)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt):
|
||||
im_A_sk_tif_scaled = plt.imread("AuLait_gray_png_skout_scaledup.tif")
|
||||
return (im_A_sk_tif_scaled,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_sk_tif_scaled):
|
||||
im_A_sk_tif_scaled.shape
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(im_A_sk_tif_scaled, plt):
|
||||
plt.imshow(im_A_sk_tif_scaled)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk1/s1.py.html
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk2/GUV24_bead_Crop.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk2/GUV24_bead_crop.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk2/Homework2.pdf
Normal file
|
After Width: | Height: | Size: 677 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk2/microarray_crop.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 22 KiB |
357
courses/uoph410-510a_Image-Analysis/wk2/s2.py
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib, matplotlib.pyplot as plt
|
||||
plt.ion()
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
|
||||
return (np,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from skimage import io
|
||||
from skimage.filters import threshold_otsu, threshold_local
|
||||
|
||||
return io, threshold_local, threshold_otsu
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework2.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## 1. Thresholding
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
robert_mapplethrope_calla_lily_1984_png = io.imread("robert-mapplethrope-calla-lily-1984.png", as_gray=True)
|
||||
return (robert_mapplethrope_calla_lily_1984_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, robert_mapplethrope_calla_lily_1984_png):
|
||||
fig1, ax1 = plt.subplots()
|
||||
p1 = ax1.imshow(robert_mapplethrope_calla_lily_1984_png, cmap="gray")
|
||||
fig1.colorbar(p1, ax=ax1)
|
||||
fig1
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(robert_mapplethrope_calla_lily_1984_png, threshold_otsu):
|
||||
robert_mapplethrope_calla_lily_global_threshold = threshold_otsu(robert_mapplethrope_calla_lily_1984_png)
|
||||
robert_mapplethrope_calla_lily_global_threshold # print
|
||||
return (robert_mapplethrope_calla_lily_global_threshold,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
plt,
|
||||
robert_mapplethrope_calla_lily_1984_png,
|
||||
robert_mapplethrope_calla_lily_global_threshold,
|
||||
):
|
||||
fig2, (ax2a, ax2b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax2a.hist(robert_mapplethrope_calla_lily_1984_png.flatten(), log=True, bins="auto")
|
||||
ax2a.vlines(robert_mapplethrope_calla_lily_global_threshold, 0, 80_000, color="r")
|
||||
p2b = ax2b.imshow(robert_mapplethrope_calla_lily_1984_png > robert_mapplethrope_calla_lily_global_threshold, cmap="gray")
|
||||
fig2.colorbar(p2b, ax=ax2b)
|
||||
fig2
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io, plt):
|
||||
fig3, ax3 = plt.subplots()
|
||||
istanbul_arch_museum_gray_crop_png = io.imread("istanbul_arch_museum_gray_crop.png", as_gray=True)
|
||||
p3 = ax3.imshow(istanbul_arch_museum_gray_crop_png, cmap="gray")
|
||||
fig3.colorbar(p3, ax=ax3)
|
||||
fig3
|
||||
return (istanbul_arch_museum_gray_crop_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(istanbul_arch_museum_gray_crop_png, threshold_otsu):
|
||||
istanbul_global_threshold = threshold_otsu(istanbul_arch_museum_gray_crop_png)
|
||||
istanbul_global_threshold # print
|
||||
return (istanbul_global_threshold,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(istanbul_arch_museum_gray_crop_png, istanbul_global_threshold, plt):
|
||||
fig4, (ax4a, ax4b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax4a.hist(istanbul_arch_museum_gray_crop_png.flatten(), log=True, bins="auto")
|
||||
ax4a.vlines(istanbul_global_threshold, 0, 300_000, color='r')
|
||||
p4b = ax4b.imshow(istanbul_arch_museum_gray_crop_png > istanbul_global_threshold, cmap="gray")
|
||||
fig4.colorbar(p4b, ax=ax4b)
|
||||
fig4
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
robert_mapplethrope_calla_lily_1984_crop_png = io.imread("robert-mapplethrope-calla-lily-1984_CROP.png", as_gray=True)
|
||||
return (robert_mapplethrope_calla_lily_1984_crop_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, robert_mapplethrope_calla_lily_1984_crop_png):
|
||||
fig5, ax5 = plt.subplots()
|
||||
p5 = ax5.imshow(robert_mapplethrope_calla_lily_1984_crop_png, cmap="gray")
|
||||
fig5.colorbar(p5, ax=ax5)
|
||||
fig5
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(robert_mapplethrope_calla_lily_1984_crop_png, threshold_otsu):
|
||||
robert_mapplethrope_calla_lily_crop_global_threshold = threshold_otsu(robert_mapplethrope_calla_lily_1984_crop_png)
|
||||
robert_mapplethrope_calla_lily_crop_global_threshold # print
|
||||
return (robert_mapplethrope_calla_lily_crop_global_threshold,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
plt,
|
||||
robert_mapplethrope_calla_lily_1984_crop_png,
|
||||
robert_mapplethrope_calla_lily_crop_global_threshold,
|
||||
):
|
||||
fig6, (ax6a, ax6b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax6a.hist(robert_mapplethrope_calla_lily_1984_crop_png.flatten(), log=True, bins="auto")
|
||||
ax6a.vlines(robert_mapplethrope_calla_lily_crop_global_threshold, 0, 80_000, color="r")
|
||||
p6b = ax6b.imshow(robert_mapplethrope_calla_lily_1984_crop_png > robert_mapplethrope_calla_lily_crop_global_threshold, cmap="gray")
|
||||
fig6.colorbar(p6b, ax=ax6b)
|
||||
fig6
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## 2. Thresholding, again
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
istanbul_arch_museum_gray_crop_png,
|
||||
plt,
|
||||
robert_mapplethrope_calla_lily_1984_crop_png,
|
||||
robert_mapplethrope_calla_lily_1984_png,
|
||||
threshold_local,
|
||||
):
|
||||
fig7, (ax7a, ax7b, ax7c) = plt.subplots(1, 3, figsize=(12, 4))
|
||||
p7a = ax7a.imshow(robert_mapplethrope_calla_lily_1984_png > threshold_local(robert_mapplethrope_calla_lily_1984_png, block_size=123), cmap="gray")
|
||||
fig7.colorbar(p7a, ax=ax7a)
|
||||
p7b = ax7b.imshow(istanbul_arch_museum_gray_crop_png > threshold_local(istanbul_arch_museum_gray_crop_png, block_size=123), cmap="gray")
|
||||
fig7.colorbar(p7b, ax=ax7b)
|
||||
p7c = ax7c.imshow(robert_mapplethrope_calla_lily_1984_crop_png > threshold_local(robert_mapplethrope_calla_lily_1984_crop_png, block_size=123), cmap="gray")
|
||||
fig7.colorbar(p7c, ax=ax7c)
|
||||
fig7
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## 3. Protein density
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io, plt):
|
||||
fig8, ax8 = plt.subplots()
|
||||
microarray_crop_png = io.imread("microarray_crop.png", as_gray=True)
|
||||
p8 = ax8.imshow(microarray_crop_png, cmap="gray")
|
||||
fig8.colorbar(p8, ax=ax8)
|
||||
fig8
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## 4. Non-uniform background subtraction
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io, plt):
|
||||
fig9, ax9 = plt.subplots()
|
||||
GUV24_bead_crop_png = io.imread("GUV24_bead_Crop.png", as_gray=True)
|
||||
p9 = ax9.imshow(GUV24_bead_crop_png, cmap="gray")
|
||||
fig9.colorbar(p9, ax=ax9)
|
||||
fig9
|
||||
return (GUV24_bead_crop_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, np):
|
||||
x = np.arange(GUV24_bead_crop_png.shape[0])
|
||||
y = np.arange(GUV24_bead_crop_png.shape[1])
|
||||
xs, ys = np.meshgrid(x, y)
|
||||
return x, xs, ys
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, plt, xs, ys):
|
||||
fig10, ax10 = plt.subplots()
|
||||
ax10 = plt.axes(projection ='3d')
|
||||
p10 = ax10.plot_surface(xs, ys, GUV24_bead_crop_png, cmap="viridis")
|
||||
fig10
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
### b.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, np, xs):
|
||||
w = np.vstack([xs.ravel(), np.ones(xs.size)]).T
|
||||
mx, c = np.linalg.lstsq(w, GUV24_bead_crop_png.ravel())[0] # (c-410) 3pt alternative
|
||||
(mx, c)
|
||||
return c, mx
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, c, mx, plt, x, xs, ys):
|
||||
fig11, (ax11a, ax11b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax11a.plot(x, mx * x + c, c='r')
|
||||
ax11a.scatter(xs.ravel(), GUV24_bead_crop_png.ravel(), s=4)
|
||||
ax11b.scatter(ys.ravel(), GUV24_bead_crop_png.ravel(), s=4)
|
||||
fig11
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
### c.
|
||||
#### 410:
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, np, xs, ys):
|
||||
# z = m @ w + c
|
||||
w2 = np.vstack([xs.ravel(), ys.ravel(), np.ones(GUV24_bead_crop_png.size)]).T
|
||||
mx2, my2, c2 = np.linalg.lstsq(w2, GUV24_bead_crop_png.ravel())[0]
|
||||
(mx2, my2, c2)
|
||||
return c2, mx2, my2
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, c2, mx2, my2, plt, xs, ys):
|
||||
fig12, ax12 = plt.subplots()
|
||||
ax12 = plt.axes(projection ='3d')
|
||||
ax12.plot_surface(xs, ys, GUV24_bead_crop_png, cmap="viridis", alpha=0.3)
|
||||
ax12.plot_surface(xs, ys, mx2 * xs + my2 * ys + c2, cmap="plasma")
|
||||
fig12
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, c2, mx2, my2, plt, xs, ys):
|
||||
fig13, ax13 = plt.subplots()
|
||||
ax13 = plt.axes(projection ='3d')
|
||||
ax13.plot_surface(xs, ys, GUV24_bead_crop_png - (mx2 * xs + my2 * ys + c2), cmap="viridis")
|
||||
fig13
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, c2, mx2, my2, plt, xs, ys):
|
||||
fig14, ax14 = plt.subplots()
|
||||
p14 = ax14.imshow(GUV24_bead_crop_png - (mx2 * xs + my2 * ys + c2), cmap="gray")
|
||||
fig14.colorbar(p14, ax=ax14)
|
||||
fig14
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
#### 510:
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, np, xs, ys):
|
||||
# z = m @ w + c
|
||||
w3 = np.vstack([xs.ravel(), np.square(xs.ravel()),
|
||||
ys.ravel(), np.square(ys.ravel()),
|
||||
np.ones(GUV24_bead_crop_png.size)]).T
|
||||
mx3, mx3x, my3, my3y, c3 = np.linalg.lstsq(w3, GUV24_bead_crop_png.ravel())[0]
|
||||
(mx3, mx3x, my3, my3y, c3)
|
||||
return c3, mx3, mx3x, my3, my3y
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, c3, mx3, mx3x, my3, my3y, np, plt, xs, ys):
|
||||
fig15, ax15 = plt.subplots()
|
||||
ax15 = plt.axes(projection ='3d')
|
||||
ax15.plot_surface(xs, ys, GUV24_bead_crop_png, cmap="viridis", alpha=0.3)
|
||||
ax15.plot_surface(xs, ys, mx3 * xs + mx3x * np.square(xs) + my3 * ys + my3y * np.square(ys) + c3, cmap="plasma")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, c3, mx3, mx3x, my3, my3y, np, plt, xs, ys):
|
||||
fig16, ax16 = plt.subplots()
|
||||
p16 = ax16.imshow(GUV24_bead_crop_png - (mx3 * xs + mx3x * np.square(xs) + my3 * ys + my3y * np.square(ys) + c3), cmap="gray")
|
||||
fig16.colorbar(p16, ax=ax16)
|
||||
fig16
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(GUV24_bead_crop_png, c3, mx3, mx3x, my3, my3y, np, plt, xs, ys):
|
||||
fig17, ax17 = plt.subplots()
|
||||
ax17 = plt.axes(projection ='3d')
|
||||
ax17.plot_surface(xs, ys, GUV24_bead_crop_png -
|
||||
(mx3 * xs + mx3x * np.square(xs) + my3 * ys + my3y * np.square(ys) + c3), cmap="viridis")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk2/s2.py.html
Normal file
|
After Width: | Height: | Size: 761 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk3/Homework3.pdf
Normal file
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 888 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk3/ennis-house.png
Normal file
|
After Width: | Height: | Size: 7.9 MiB |
BIN
courses/uoph410-510a_Image-Analysis/wk3/escher-relativity.png
Normal file
|
After Width: | Height: | Size: 404 KiB |
554
courses/uoph410-510a_Image-Analysis/wk3/s3.py
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib, matplotlib.pyplot as plt
|
||||
plt.ion();
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
|
||||
return (np,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from skimage import io
|
||||
from skimage.filters import gaussian, median, threshold_otsu
|
||||
|
||||
return gaussian, io, median, threshold_otsu
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import scipy.ndimage as ndi
|
||||
|
||||
return (ndi,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework3.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Convolution and Filtering
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
escher_relativity_png = io.imread("escher-relativity.png", as_gray=True)
|
||||
return (escher_relativity_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png, plt):
|
||||
fig1, ax1 = plt.subplots()
|
||||
p1 = ax1.imshow(escher_relativity_png, cmap="gray")
|
||||
cbar1 = fig1.colorbar(p1, ax=ax1)
|
||||
fig1
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
avgker11 = np.ones((11, 11)) / np.square(11)
|
||||
return (avgker11,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(avgker11, escher_relativity_png, ndi):
|
||||
escher_relativity_png_avgd_const = ndi.convolve(escher_relativity_png, avgker11, mode="constant")
|
||||
escher_relativity_png_avgd_miror = ndi.convolve(escher_relativity_png, avgker11, mode="mirror")
|
||||
return escher_relativity_png_avgd_const, escher_relativity_png_avgd_miror
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png_avgd_const, escher_relativity_png_avgd_miror, plt):
|
||||
fig2, (ax2a, ax2b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
p2a = ax2a.imshow(escher_relativity_png_avgd_const, cmap="gray")
|
||||
p2b = ax2b.imshow(escher_relativity_png_avgd_miror, cmap="gray")
|
||||
fig2.colorbar(p2a, ax=ax2a)
|
||||
fig2.colorbar(p2b, ax=ax2b)
|
||||
fig2
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Gaussian Filtering
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def gaussker(sgm2, shape=(11, 11)):
|
||||
xs, ys = np.meshgrid(np.arange(shape[0]), np.arange(shape[1]))
|
||||
r2s = np.square(xs - shape[0] // 2) + np.square(ys - shape[0] // 2)
|
||||
e = np.exp(- r2s / (2 * sgm2))
|
||||
return e / np.sum(e) # return normalized kernel
|
||||
|
||||
return (gaussker,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gaussker, plt):
|
||||
fig3, (ax3a, ax3b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
p3a = ax3a.imshow(gaussker(3))
|
||||
p3b = ax3b.imshow(gaussker(7))
|
||||
fig3.colorbar(p3a, ax=ax3a)
|
||||
fig3.colorbar(p3b, ax=ax3b)
|
||||
fig3
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png, gaussker, ndi):
|
||||
escher_relativity_png_gaussd3 = ndi.convolve(escher_relativity_png, gaussker(3))
|
||||
escher_relativity_png_gaussd7 = ndi.convolve(escher_relativity_png, gaussker(7))
|
||||
return escher_relativity_png_gaussd3, escher_relativity_png_gaussd7
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png_gaussd3, escher_relativity_png_gaussd7, plt):
|
||||
fig4, (ax4a, ax4b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
p4a = ax4a.imshow(escher_relativity_png_gaussd3, cmap="gray")
|
||||
p4b = ax4b.imshow(escher_relativity_png_gaussd7, cmap="gray")
|
||||
fig4.colorbar(p4a, ax=ax4a)
|
||||
fig4.colorbar(p4b, ax=ax4b)
|
||||
fig4
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png, gaussian, np):
|
||||
escher_relativity_png_gaussdsk7 = gaussian(escher_relativity_png, np.sqrt(7))
|
||||
return (escher_relativity_png_gaussdsk7,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png_gaussdsk7, plt):
|
||||
fig5, ax5 = plt.subplots()
|
||||
p5 = ax5.imshow(escher_relativity_png_gaussdsk7, cmap="gray")
|
||||
fig5.colorbar(p5, ax=ax5)
|
||||
fig5
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png_gaussd7, escher_relativity_png_gaussdsk7, np):
|
||||
escher_relativity_png_skdiff = escher_relativity_png_gaussdsk7 - escher_relativity_png_gaussd7
|
||||
escher_relativity_png_skdiff = escher_relativity_png_skdiff - np.min(escher_relativity_png_skdiff)
|
||||
return (escher_relativity_png_skdiff,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png_skdiff, plt):
|
||||
fig6, ax6 = plt.subplots()
|
||||
p6 = ax6.imshow(escher_relativity_png_skdiff, cmap="gray")
|
||||
fig6.colorbar(p6, ax=ax6)
|
||||
fig6
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Median Filtering
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png, median, np):
|
||||
escher_relativity_png_median7 = median(escher_relativity_png, np.ones((7, 7)))
|
||||
return (escher_relativity_png_median7,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(escher_relativity_png_median7, plt):
|
||||
fig7, ax7 = plt.subplots()
|
||||
p7 = ax7.imshow(escher_relativity_png_median7, cmap="gray")
|
||||
fig7.colorbar(p7, ax=ax7)
|
||||
fig7
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Filtering and Thresholding
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
makeup_richardprince_1983_gray_png = io.imread("MakeUp_RichardPrince_1983_gray.png", as_gray=True)
|
||||
return (makeup_richardprince_1983_gray_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(makeup_richardprince_1983_gray_png, plt):
|
||||
fig8, ax8 = plt.subplots()
|
||||
p8 = ax8.imshow(makeup_richardprince_1983_gray_png, cmap="gray")
|
||||
fig8.colorbar(p8, ax=ax8)
|
||||
fig8
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gaussian, makeup_richardprince_1983_gray_png, np, threshold_otsu):
|
||||
makeup_richardprince_1983_gray_png_gaussian = 255 * gaussian(makeup_richardprince_1983_gray_png, np.sqrt(51))
|
||||
makeup_richardprince_1983_gray_png_gaussian_gthreshold = threshold_otsu(makeup_richardprince_1983_gray_png_gaussian)
|
||||
makeup_richardprince_1983_gray_png_gaussian_threshd = makeup_richardprince_1983_gray_png_gaussian > makeup_richardprince_1983_gray_png_gaussian_gthreshold
|
||||
return (makeup_richardprince_1983_gray_png_gaussian_threshd,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(makeup_richardprince_1983_gray_png, median, np, threshold_otsu):
|
||||
makeup_richardprince_1983_gray_png_median = median(makeup_richardprince_1983_gray_png, np.ones((51, 51)))
|
||||
makeup_richardprince_1983_gray_png_median_gthreshold = threshold_otsu(makeup_richardprince_1983_gray_png_median)
|
||||
makeup_richardprince_1983_gray_png_median_threshd = makeup_richardprince_1983_gray_png_median > makeup_richardprince_1983_gray_png_median_gthreshold
|
||||
return (makeup_richardprince_1983_gray_png_median_threshd,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
makeup_richardprince_1983_gray_png_gaussian_threshd,
|
||||
makeup_richardprince_1983_gray_png_median_threshd,
|
||||
plt,
|
||||
):
|
||||
fig9, (ax9a, ax9b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
p9a = ax9a.imshow(makeup_richardprince_1983_gray_png_gaussian_threshd, cmap="gray")
|
||||
fig9.colorbar(p9a, ax=ax9a)
|
||||
p9b = ax9b.imshow(makeup_richardprince_1983_gray_png_median_threshd, cmap="gray")
|
||||
fig9.colorbar(p9b, ax=ax9b)
|
||||
fig9
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## High-pass Filtering
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
elevator_to_the_gallows_png = io.imread("Elevator_to_the_gallows.png", as_gray=True)
|
||||
return (elevator_to_the_gallows_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(elevator_to_the_gallows_png, plt):
|
||||
fig10, ax10 = plt.subplots()
|
||||
ax10.imshow(elevator_to_the_gallows_png, cmap="gray")
|
||||
fig10
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gaussian, np):
|
||||
def gausshighpass(image, sigma=np.sqrt(7)):
|
||||
gaussd = (np.max(image) - np.min(image)) * gaussian(image, sigma)
|
||||
diff = image - gaussd
|
||||
diff = diff - np.min(diff)
|
||||
return (255 / np.max(diff)) * diff
|
||||
|
||||
return (gausshighpass,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(elevator_to_the_gallows_png, gausshighpass):
|
||||
elevator_to_the_gallows_png_highpass = gausshighpass(elevator_to_the_gallows_png, sigma=21)
|
||||
return (elevator_to_the_gallows_png_highpass,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(elevator_to_the_gallows_png_highpass, plt):
|
||||
fig11, ax11 = plt.subplots()
|
||||
ax11.imshow(elevator_to_the_gallows_png_highpass, cmap="gray")
|
||||
fig11
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(elevator_to_the_gallows_png_highpass, threshold_otsu):
|
||||
elevator_to_the_gallows_png_highpass_threshold = threshold_otsu(elevator_to_the_gallows_png_highpass)
|
||||
elevator_to_the_gallows_png_highthresh = elevator_to_the_gallows_png_highpass > elevator_to_the_gallows_png_highpass_threshold
|
||||
return (elevator_to_the_gallows_png_highthresh,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(elevator_to_the_gallows_png_highthresh, plt):
|
||||
fig12, ax12 = plt.subplots()
|
||||
ax12.imshow(elevator_to_the_gallows_png_highthresh, cmap="gray")
|
||||
fig12
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Band-pass Filtering
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
gaussians_s2_to_s50_px_tif = io.imread("gaussians_s2_to_s50_px.tif", as_gray=True)
|
||||
return (gaussians_s2_to_s50_px_tif,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gaussians_s2_to_s50_px_tif, plt):
|
||||
fig13, (ax13a, ax13b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax13a.imshow(gaussians_s2_to_s50_px_tif, cmap="gray")
|
||||
ax13a.hlines(1240, 0, 3200, color="magenta")
|
||||
ax13b.plot(gaussians_s2_to_s50_px_tif[1240, :])
|
||||
fig13
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gaussian, np):
|
||||
def gausslowpass(image, sigma=np.sqrt(7)):
|
||||
gaussd = (np.max(image) - np.min(image)) * gaussian(image, sigma)
|
||||
return (255 / np.max(gaussd)) * gaussd
|
||||
|
||||
return (gausslowpass,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gausshighpass, gaussians_s2_to_s50_px_tif, gausslowpass):
|
||||
gaussians_s2_to_s50_px_tif_bandpassed = gausslowpass(gausshighpass(
|
||||
gaussians_s2_to_s50_px_tif,
|
||||
sigma=20), sigma=10)
|
||||
return (gaussians_s2_to_s50_px_tif_bandpassed,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gaussians_s2_to_s50_px_tif_bandpassed, plt):
|
||||
fig14, (ax14a, ax14b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax14a.imshow(gaussians_s2_to_s50_px_tif_bandpassed, cmap="gray")
|
||||
ax14a.hlines(1240, 0, 3200, color="magenta")
|
||||
ax14b.plot(gaussians_s2_to_s50_px_tif_bandpassed[1240, :])
|
||||
fig14
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Signal to Noise Ratio
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
rng = np.random.default_rng()
|
||||
def sim_image(r, b=2, t=2, size=(27, 27)):
|
||||
bg = rng.poisson(lam=b * t, size=size)
|
||||
sg = np.zeros_like(bg)
|
||||
sg[sg.shape[0] // 2, sg.shape[1] // 2] = rng.poisson(lam=r*t)
|
||||
return bg + sg
|
||||
|
||||
return (sim_image,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, sim_image):
|
||||
fig15, (ax15a, ax15b, ax15c) = plt.subplots(1, 3, figsize=(10, 4))
|
||||
ax15a.imshow(sim_image(2, t=1), cmap="gray")
|
||||
ax15b.imshow(sim_image(6, t=1), cmap="gray")
|
||||
ax15c.imshow(sim_image(10, t=1), cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, sim_image):
|
||||
exposure_sims = [ sim_image(0.5, t=t) for t in range(0, 300) ]
|
||||
sns = [s[27//2, 27//2] / np.std(s) for s in exposure_sims]
|
||||
return (sns,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, sns):
|
||||
fig16, ax16 = plt.subplots()
|
||||
ax16.scatter(range(0, 300), sns)
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## A little bit of Fourier Transforming
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
Lincoln_Coleman_png = io.imread("Lincoln_Coleman_40-copyright-havecamerawilltravel-com_crop512_gray.png", as_gray=True)
|
||||
return (Lincoln_Coleman_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Lincoln_Coleman_png, plt):
|
||||
fig17, ax17 = plt.subplots()
|
||||
ax17.imshow(Lincoln_Coleman_png, cmap="grey")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
# %load fourier_masking_HWproblem.py
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io, np, plt):
|
||||
# %load fourier_masking_HWproblem.py
|
||||
# fourier_masking_HWproblem.py
|
||||
"""
|
||||
Author: Raghuveer Parthasarathy
|
||||
Created on Tue Oct 8 07:25:53 2024
|
||||
Last modified on Oct. 12, 2024
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
For a homework problem on masking Fourier Transforms
|
||||
|
||||
"""
|
||||
|
||||
#import numpy as np
|
||||
#import matplotlib.pyplot as plt
|
||||
import os
|
||||
#from skimage import io # input output sub-package
|
||||
|
||||
|
||||
# %% Load the image
|
||||
|
||||
parentDir = r"./"
|
||||
fileName = r"Lincoln_Coleman_40-copyright-havecamerawilltravel-com_crop512_gray.png"
|
||||
|
||||
im = io.imread(os.path.join(parentDir, fileName))
|
||||
|
||||
if im.ndim > 2:
|
||||
# A bit silly, since I know this is 2D
|
||||
im = np.mean(im, axis=2, dtype=im.dtype)
|
||||
|
||||
print("Image shape: ", im.shape)
|
||||
# Image size; I'm not checking if it's square!
|
||||
# The Lincoln Memorial image is 512x512
|
||||
N = im.shape[0]
|
||||
|
||||
plt.figure()
|
||||
plt.imshow(im, "gray")
|
||||
plt.title("Original Image")
|
||||
|
||||
# %% Fourier Transform
|
||||
|
||||
# Perform 2D Fourier transform
|
||||
F = np.fft.fft2(im) # Fast Fourier Transform
|
||||
F_shifted = np.fft.fftshift(F) # Shift so zero frequency is in the center
|
||||
|
||||
# Calculate the amplitude and phase
|
||||
amplitude = np.abs(F_shifted)
|
||||
phase = np.angle(F_shifted)
|
||||
|
||||
# Display amplitude as an image
|
||||
plt.figure()
|
||||
plt.title("Fourier Transform Amplitude (log scale)")
|
||||
# Should maybe add an offset to avoid -Inf,
|
||||
# but I've tested and there are no zeros.
|
||||
plt.imshow(np.log(amplitude), cmap="gray")
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
|
||||
# Display phase as an image
|
||||
plt.figure()
|
||||
plt.title("Fourier Transform Phase (radians)")
|
||||
plt.imshow(phase)
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
|
||||
# %% Masking
|
||||
|
||||
# "Fundamental frequency" for the mask
|
||||
f0 = 15 # I determined this "by hand"
|
||||
# Full width of the mask -- should be an even number
|
||||
df = 4
|
||||
|
||||
# Create a mask array
|
||||
mask = np.ones((N, N))
|
||||
for k in range(1, N // (2 * f0)):
|
||||
center_f = N / 2 + k * f0
|
||||
mask[:, int(center_f - df / 2) : int(center_f + df / 2)] = 0
|
||||
center_f = N / 2 - k * f0
|
||||
mask[:, int(center_f - df / 2) : int(center_f + df / 2)] = 0
|
||||
|
||||
# Create a new amplitude array that is the original multiplied by this mask
|
||||
new_amplitude = amplitude * mask
|
||||
# new_amplitude = amplitude * (1.0 - mask) # show just the *difference*!
|
||||
|
||||
# Display the new amplitude as an image
|
||||
plt.figure()
|
||||
plt.title("Amplitude * Mask")
|
||||
plt.imshow(np.log(new_amplitude + 0.1), cmap="gray") # + 0.1 because of zeros.
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
|
||||
|
||||
# Combine new amplitude with original phase
|
||||
new_F_shifted = new_amplitude * np.exp(1j * phase)
|
||||
|
||||
# Perform the inverse Fourier transform
|
||||
new_F = np.fft.ifftshift(new_F_shifted)
|
||||
new_im = np.fft.ifft2(new_F)
|
||||
new_im = np.abs(new_im)
|
||||
|
||||
# Display the resulting image
|
||||
plt.figure()
|
||||
plt.title("Image based on Inverse FT")
|
||||
plt.imshow(new_im, cmap="gray")
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk3/s3.py.html
Normal file
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 118 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk4/Homework4.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk4/Homework4_files.zip
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
courses/uoph410-510a_Image-Analysis/wk4/emitters_33px_100ph.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
|
@ -0,0 +1,87 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# frequency_modulation_hw.py
|
||||
|
||||
"""
|
||||
Author: Raghuveer Parthasarathy
|
||||
Created on Oct. 17, 2024
|
||||
Last modified on Oct. 18, 2024
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
For a homework problem on frequency modulation
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import os
|
||||
from skimage import io # input output sub-package
|
||||
|
||||
#%% Load the image
|
||||
|
||||
parentDir = r'C:\Users\Raghu\Documents\Teaching\Image Analysis Course\Images for Class'
|
||||
fileName = r'Buster_Keaton_General_Train_512.png'
|
||||
|
||||
im = io.imread(os.path.join(parentDir, fileName))
|
||||
|
||||
print('Image shape: ', im.shape)
|
||||
N = im.shape[0]
|
||||
|
||||
plt.figure()
|
||||
plt.imshow(im, 'gray')
|
||||
plt.title('Original Image')
|
||||
|
||||
|
||||
#%% Multiply by sine waves
|
||||
|
||||
xc = np.linspace(-N/2, N/2, N)
|
||||
x, y = np.meshgrid(xc, xc)
|
||||
Px = 8
|
||||
Py = 15
|
||||
sineWave = np.sin(2.0*np.pi*x/Px) # + np.sin(2.0*np.pi*y/Py)
|
||||
im_mod = im*sineWave
|
||||
# Rescale to [0, 255]
|
||||
im_mod = 255.0*(im_mod - np.min(im_mod)) / (np.max(im_mod) - np.min(im_mod))
|
||||
im_mod = np.clip(im_mod, 0, 255).astype('uint8')
|
||||
plt.figure()
|
||||
plt.imshow(im_mod, 'gray')
|
||||
plt.title('Modified Image')
|
||||
|
||||
# Output
|
||||
outputFileName = r'Buster_Keaton_General_Train_512_sineMod.png'
|
||||
|
||||
io.imsave(os.path.join(parentDir, outputFileName), im_mod)
|
||||
|
||||
#%% Fourier Transforms
|
||||
|
||||
# Perform 2D Fourier transform of the original
|
||||
F = np.fft.fft2(im) # Fast Fourier Transform
|
||||
F_shifted = np.fft.fftshift(F) # Shift so zero frequency is in the center
|
||||
|
||||
# Calculate the amplitude and phase
|
||||
amplitude = np.abs(F_shifted)
|
||||
phase = np.angle(F_shifted)
|
||||
|
||||
# Display amplitude as an image
|
||||
plt.figure()
|
||||
plt.title("Fourier Transform Amplitude (log scale)")
|
||||
plt.imshow(np.log(amplitude), cmap='gray')
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
|
||||
# Perform 2D Fourier transform of the modified image
|
||||
F_mod = np.fft.fft2(im_mod) # Fast Fourier Transform
|
||||
F_shifted_mod = np.fft.fftshift(F_mod) # Shift so zero frequency is in the center
|
||||
|
||||
# Calculate the amplitude and phase
|
||||
amplitude_mod = np.abs(F_shifted_mod)
|
||||
phase_mod = np.angle(F_shifted_mod)
|
||||
|
||||
# Display amplitude as an image
|
||||
plt.figure()
|
||||
plt.title("Fourier Transform Amplitude (log scale): modified image")
|
||||
plt.imshow(np.log(amplitude_mod), cmap='gray')
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
401
courses/uoph410-510a_Image-Analysis/wk4/s4.py
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
|
||||
return (np,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from skimage import io, filters
|
||||
|
||||
return filters, io
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import scipy as si
|
||||
import scipy.ndimage as nd
|
||||
|
||||
return nd, si
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
plt.ion();
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework4.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Frequency Modulation
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
buster_keaton_general_train_512_png = io.imread("Buster_Keaton_General_Train_512.png", as_gray=True)
|
||||
buster_keaton_general_train_512_sinmod_png = io.imread("Buster_Keaton_General_Train_512_sineMod.png", as_gray=True)
|
||||
return (
|
||||
buster_keaton_general_train_512_png,
|
||||
buster_keaton_general_train_512_sinmod_png,
|
||||
)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
buster_keaton_general_train_512_png,
|
||||
buster_keaton_general_train_512_sinmod_png,
|
||||
plt,
|
||||
):
|
||||
fig1, (ax1a, ax1b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax1a.imshow(buster_keaton_general_train_512_png, cmap="gray")
|
||||
ax1b.imshow(buster_keaton_general_train_512_sinmod_png, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
buster_keaton_general_train_512_png,
|
||||
buster_keaton_general_train_512_sinmod_png,
|
||||
np,
|
||||
):
|
||||
buster_keaton_general_train_512_fft = np.abs(np.fft.fftshift(np.fft.fft2(buster_keaton_general_train_512_png)))
|
||||
buster_keaton_general_train_512_sinmod_fft = np.abs(np.fft.fftshift(np.fft.fft2(buster_keaton_general_train_512_sinmod_png)))
|
||||
return (
|
||||
buster_keaton_general_train_512_fft,
|
||||
buster_keaton_general_train_512_sinmod_fft,
|
||||
)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
buster_keaton_general_train_512_fft,
|
||||
buster_keaton_general_train_512_sinmod_fft,
|
||||
np,
|
||||
plt,
|
||||
):
|
||||
fig2, (ax2a, ax2b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax2a.imshow(np.log(buster_keaton_general_train_512_fft), cmap="gray")
|
||||
ax2b.imshow(np.log(buster_keaton_general_train_512_sinmod_fft), cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Quantized Aggregates
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
emitters_33px_100ph_png = io.imread("emitters_33px_100ph.png")
|
||||
return (emitters_33px_100ph_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(emitters_33px_100ph_png, plt):
|
||||
fig3, ax3 = plt.subplots()
|
||||
ax3.imshow(emitters_33px_100ph_png, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(emitters_33px_100ph_png, plt):
|
||||
fig4, ax4 = plt.subplots()
|
||||
ax4.hist(emitters_33px_100ph_png.ravel(), bins="auto")
|
||||
fig4
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(emitters_33px_100ph_png, filters):
|
||||
emitters_33px_100ph_hflt = emitters_33px_100ph_png - 255 * filters.gaussian(emitters_33px_100ph_png, 8, mode="nearest")
|
||||
return (emitters_33px_100ph_hflt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(emitters_33px_100ph_hflt, plt):
|
||||
fig6, (ax6a, ax6b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax6a.imshow(emitters_33px_100ph_hflt, cmap="gray")
|
||||
ax6b.hist(emitters_33px_100ph_hflt.ravel(), bins=20)
|
||||
fig6
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(emitters_33px_100ph_hflt, np):
|
||||
ones = np.ones_like(emitters_33px_100ph_hflt, dtype=bool)
|
||||
zeros = np.zeros_like(ones, dtype=bool)
|
||||
x, y = np.arange(ones.shape[0]), np.arange(ones.shape[1])
|
||||
xs, ys = np.meshgrid(x, y)
|
||||
masks = [np.where((np.abs(xs - 33 * i) <= 2) & (np.abs(ys - 33 * j) <= 2), ones, zeros)
|
||||
for i in range(1, 11) for j in range(1, 11)]
|
||||
# mask = np.where((xs % (33 + 4) > (33 - 4)) & (ys % (33 + 4) > (33 - 4)), ones, zeros)
|
||||
mask = sum(masks)
|
||||
return mask, masks
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(emitters_33px_100ph_hflt, masks, np):
|
||||
intensities = [np.sum(emitters_33px_100ph_hflt, where=m) for m in masks]
|
||||
return (intensities,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(intensities, mask, plt):
|
||||
fig7, (ax7a, ax7b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax7a.imshow(mask, cmap="gray")
|
||||
counts, edges, _ = ax7b.hist(intensities, bins=25)
|
||||
fig7
|
||||
return counts, edges
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(counts, edges, np):
|
||||
irange = (np.max(edges) - np.min(edges))
|
||||
imin = np.min(edges)
|
||||
(sum(counts[edges[1:] <= (irange/3) + imin]),
|
||||
sum(counts[((irange/3) + imin < edges[1:]) & (edges[1:] <= (2*irange/3) + imin)]),
|
||||
sum(counts[((2*irange/3) + imin < edges[1:])])
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## A High-Resolution PSF
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, si):
|
||||
def psfker(l, NA=0.9, side=1.0, N=101, center=(0.0, 0.0)):
|
||||
xs, ys = np.meshgrid(np.linspace(0.0, side, N), np.linspace(0.0, side, N))
|
||||
r2s = np.square(xs - side / 2 - center[0]) + np.square(ys - side / 2 - center[1])
|
||||
v = 2 * np.pi * NA * np.sqrt(r2s) / l
|
||||
psf = 4 * np.square(si.special.j1(v) / v)
|
||||
nans = np.isnan(psf)
|
||||
psf[nans] = 1
|
||||
return psf / np.sum(psf)
|
||||
|
||||
return (psfker,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, psfker):
|
||||
fig8, (ax8a, ax8b, ax8c) = plt.subplots(1, 3, figsize=(8, 2))
|
||||
ax8a.imshow(psfker(0.5), cmap="gray")
|
||||
ax8b.imshow(psfker(0.4), cmap="gray")
|
||||
ax8c.imshow(psfker(0.4, NA=0.5), cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## A Worse Worm Image
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
fetter_celegans_cellfig10_png = io.imread("fetter_Celegans_cellfig10.jpg", as_gray=True)
|
||||
return (fetter_celegans_cellfig10_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fetter_celegans_cellfig10_png, plt):
|
||||
fig9, ax9 = plt.subplots()
|
||||
ax9.imshow(fetter_celegans_cellfig10_png, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fetter_celegans_cellfig10_png, nd, psfker):
|
||||
fetter_celegans_cellfig10_psf = nd.convolve(fetter_celegans_cellfig10_png, psfker(0.53, NA=0.7))
|
||||
return (fetter_celegans_cellfig10_psf,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fetter_celegans_cellfig10_psf, plt):
|
||||
fig10, ax10 = plt.subplots()
|
||||
ax10.imshow(fetter_celegans_cellfig10_psf, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## SNR and Poisson Noise
|
||||
$$ N_\text{photon} \sim SNR^2 $$
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Simulated Point Sources
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def pixelate(image, inscale, shape=(15, 15)):
|
||||
outscale = image.shape[0] * inscale / shape[0]
|
||||
assert outscale == image.shape[1] * inscale / shape[1]
|
||||
assert outscale.is_integer()
|
||||
|
||||
ii, jj = np.indices(image.shape)
|
||||
|
||||
ones = np.ones_like(image, dtype=bool)
|
||||
zeros = np.zeros_like(image, dtype=bool)
|
||||
|
||||
masks = [np.where((i * outscale <= ii * inscale) &
|
||||
(ii * inscale < (i + 1) * outscale)
|
||||
& (j * outscale <= jj * inscale) &
|
||||
(jj * inscale < (j + 1) * outscale),
|
||||
ones, zeros)
|
||||
for i in range(shape[0]) for j in range(shape[1])]
|
||||
|
||||
outage = np.array([np.sum(image, where=m) for m in masks]).reshape(shape)
|
||||
|
||||
return outage, outscale
|
||||
|
||||
return (pixelate,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(pixelate, psfker):
|
||||
simpoint, _ = pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150), 0.1)
|
||||
return (simpoint,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, simpoint):
|
||||
fig11, ax11 = plt.subplots()
|
||||
ax11.imshow(simpoint, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def fishify(image, N=1, rng=np.random.default_rng()):
|
||||
return rng.poisson(lam=N * (image / np.sum(image)))
|
||||
|
||||
return (fishify,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fishify, pixelate, psfker):
|
||||
simpoint50 = fishify(pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150), 0.1)[0], N=50)
|
||||
simpoint500 = fishify(pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150), 0.1)[0], N=500)
|
||||
return simpoint50, simpoint500
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, simpoint50, simpoint500):
|
||||
fig12, (ax12a, ax12b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax12a.imshow(simpoint50, cmap="gray")
|
||||
ax12b.imshow(simpoint500, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fishify, pixelate, psfker):
|
||||
simpoint50_shifted = fishify(pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150, center=(0.3, 0.3)), 0.1)[0], N=50)
|
||||
simpoint500_shifted = fishify(pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150, center=(0.3, 0.3)), 0.1)[0], N=500)
|
||||
return simpoint500_shifted, simpoint50_shifted
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, simpoint500_shifted, simpoint50_shifted):
|
||||
fig13, (ax13a, ax13b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax13a.imshow(simpoint50_shifted, cmap="gray")
|
||||
ax13b.imshow(simpoint500_shifted, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fishify, np, pixelate, psfker):
|
||||
uniform = np.ones((15, 15)) / np.sum(np.ones((15, 15)))
|
||||
simpoint_i = fishify(pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150), 0.1)[0], N=50) + fishify(np.ones((15, 15)), N=2 * 15**2)
|
||||
simpoint_ii = fishify(pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150, center=(0.03, 0.03)), 0.1)[0], N=50) + fishify(np.ones((15, 15)), N=2 * 15**2)
|
||||
simpoint_iii = fishify(pixelate(psfker(0.5, NA=0.9, side=15 * 0.1, N = 150, center=(0.03, 0.03)), 0.1)[0], N=500) + fishify(np.ones((15, 15)), N=2 * 15**2)
|
||||
return simpoint_i, simpoint_ii, simpoint_iii
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, simpoint_i, simpoint_ii, simpoint_iii):
|
||||
fig14, (ax14a, ax14b, ax14c) = plt.subplots(1, 3, figsize=(8, 2))
|
||||
ax14a.imshow(simpoint_i, cmap="gray")
|
||||
ax14b.imshow(simpoint_ii, cmap="gray")
|
||||
ax14c.imshow(simpoint_iii, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Simulating a Ring
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def ring(inner, outer, center=(0, 0), scale=1, shape=(150, 150), rtol=1e-02, atol=1e-02):
|
||||
ii, jj = np.indices(shape)
|
||||
r2s = np.square((ii - shape[0] / 2) * scale - center[0]) + np.square((jj - shape[1] / 2) * scale - center[1])
|
||||
return ((r2s < np.square(outer)) & (r2s >= np.square(inner))).astype(np.float32)
|
||||
|
||||
return (ring,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fishify, nd, plt, psfker, ring):
|
||||
fig15, (ax15a, ax15b, ax15c) = plt.subplots(1, 3, figsize=(8, 4))
|
||||
ax15a.imshow(ring(0.5, 0.6, scale=0.01), cmap="gray")
|
||||
ax15b.imshow(nd.convolve(ring(0.5, 0.6, scale=0.01), psfker(0.1), mode="nearest"), cmap="gray")
|
||||
ax15c.imshow(fishify(nd.convolve(ring(0.5, 0.6, scale=0.01), psfker(0.1), mode="nearest"), N=10_000), cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk4/s4.py.html
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk5/Homework5.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk5/Homework5_Files.zip
Normal file
290
courses/uoph410-510a_Image-Analysis/wk5/s5.py
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
rng = np.random.default_rng()
|
||||
return np, rng
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import scipy as si
|
||||
|
||||
return (si,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
plt.ion();
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework5.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## The Signal-to-Noise Ratio in Images
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(rng):
|
||||
xs = rng.poisson(lam=200, size=1000 * 500).reshape(1000, 500)
|
||||
xs.shape
|
||||
return (xs,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, xs):
|
||||
np.mean(np.mean(xs, axis=0) / np.std(xs, axis=0))
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
As = np.logspace(-6, 6, 500)
|
||||
As.shape
|
||||
return (As,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(As, np, xs):
|
||||
np.mean(np.mean(As * xs, axis=0) / np.std(As * xs, axis=0))
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(As, np, xs):
|
||||
ras = np.mean(xs, axis=0) / np.std(xs, axis=0) - np.mean(As * xs, axis=0) / np.std(As * xs, axis=0)
|
||||
np.mean(ras)
|
||||
return (ras,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, ras):
|
||||
fig, ax = plt.subplots()
|
||||
ax.hist(ras, bins="auto")
|
||||
fig
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
Zero! To within typical machine error.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Centroid Warmup
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
i = np.arange(0, 1000)
|
||||
I = 0.2 * np.sqrt(i)
|
||||
float(np.sum(i * I) / np.sum(I))
|
||||
return (i,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(i, np, rng):
|
||||
J = 30 / (i + 20) + 0.05 * rng.poisson(lam=10, size=i.size)
|
||||
float(np.sum(i * J) / np.sum(J))
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Centroid Localization
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, si):
|
||||
def psfker(l, NA=0.9, side=1.0, N=210, center=(0.0, 0.0)):
|
||||
xs, ys = np.meshgrid(np.linspace(- side / 2, side / 2, N),
|
||||
np.linspace(- side / 2, side / 2, N))
|
||||
r2s = np.square(xs - center[0]) + np.square(ys - center[1])
|
||||
v = 2 * np.pi * NA * np.sqrt(r2s) / l
|
||||
psf = 4 * np.square(si.special.j1(v) / v)
|
||||
psf[np.isnan(psf)] = 1
|
||||
scale = side / N
|
||||
return psf / np.sum(psf), scale
|
||||
|
||||
return (psfker,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def pixelate(image, inscale, shape=(7, 7)):
|
||||
outscale = image.shape[0] * inscale / shape[0]
|
||||
|
||||
out = np.sum(image.reshape(shape[0], int(image.shape[0] / shape[0]),
|
||||
shape[1], int(image.shape[1] / shape[1])),
|
||||
axis=(1, 3))
|
||||
|
||||
return out, outscale
|
||||
|
||||
return (pixelate,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def fishify(image, N=1, rng=np.random.default_rng()):
|
||||
return rng.poisson(lam=N * (image / np.sum(image)))
|
||||
|
||||
return (fishify,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(fishify, np, pixelate, psfker):
|
||||
def sim(l=0.51, NA=0.9, side=0.7, center=(0.0, 0.0), Nphoton=500, Nfine=280, bgavg=10, shape=(7, 7)):
|
||||
point, scale = psfker(l, NA=NA, side=side, N=Nfine, center=center)
|
||||
pxpt, scale = pixelate(point, scale, shape=shape)
|
||||
fg = fishify(pxpt, N=Nphoton)
|
||||
bg = fishify(np.ones(shape), N=bgavg * np.prod(shape))
|
||||
return fg + bg, scale
|
||||
|
||||
return (sim,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def centroid(im, scale=None):
|
||||
ys, xs = np.indices(im.shape)
|
||||
c = np.hstack([np.sum(xs * im), np.sum(ys * im)]) / np.sum(im)
|
||||
c = (im * np.mgrid[0:im.shape[0], 0:im.shape[1]]).sum(1).sum(1)/im.sum()
|
||||
return c if scale is None else scale * (c - np.array(im.shape) // 2)
|
||||
|
||||
return (centroid,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def rms(cs, center=(0.0, 0.0)):
|
||||
return float(np.sqrt(np.mean(np.square(cs[:,0] - center[0]) + np.square(cs[:,1] - center[1]))))
|
||||
|
||||
return (rms,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(centroid, np, sim):
|
||||
sims1 = [sim(center=(0.0, 0.0)) for m in range(100)]
|
||||
cs1 = np.array([centroid(s, scale=scale) for (s, scale) in sims1])
|
||||
return cs1, sims1
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(centroid, cs1, plt, sims1):
|
||||
fig1, (ax1a, ax1b) = plt.subplots(1, 2, figsize=(8, 4))
|
||||
ax1a.imshow(sims1[0][0], cmap="gray")
|
||||
cx, cy = centroid(sims1[0][0])
|
||||
ax1a.vlines(cx, 0, 6, color="red")
|
||||
ax1a.hlines(cy, 0, 6, color="red")
|
||||
ax1b.hist(cs1[:,0], bins="auto")
|
||||
fig1.tight_layout()
|
||||
fig1
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cs1, rms):
|
||||
rms(cs1)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(centroid, np, rms, sim):
|
||||
rmss = []
|
||||
for n in np.logspace(0, 5, 15):
|
||||
sims = [sim(Nphoton=n) for m in range(100)]
|
||||
cs = np.array([centroid(s, scale=sc) for (s, sc) in sims])
|
||||
rmss.append(rms(cs))
|
||||
return (rmss,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, plt, rmss):
|
||||
fig2, ax2 = plt.subplots()
|
||||
ax2.scatter(np.logspace(0, 5, 15), rmss)
|
||||
ax2.loglog(np.logspace(0, 5, 10), 1 / np.sqrt(np.logspace(0, 5, 10)), color="orange")
|
||||
ax2.set_aspect('equal', 'box')
|
||||
fig2.tight_layout()
|
||||
fig2
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(centroid, np, sim):
|
||||
sims3a = [sim(Nphoton=1000) for m in range(100)]
|
||||
cs3a = np.array([centroid(s, scale=sc) for (s, sc) in sims3a])
|
||||
sims3b = [sim(Nphoton=1000, center=(0.3, 0.0)) for m in range(100)]
|
||||
cs3b = np.array([centroid(s, scale=sc) for (s, sc) in sims3b])
|
||||
sims3c = [sim(Nphoton=1000, center=(-0.3, 0.0)) for m in range(100)]
|
||||
cs3c = np.array([centroid(s, scale=sc) for (s, sc) in sims3c])
|
||||
return cs3a, cs3b, cs3c
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cs3a, cs3b, cs3c, plt):
|
||||
fig3, (ax3a, ax3b, ax3c) = plt.subplots(1, 3, figsize=(9, 3))
|
||||
ax3a.hist(cs3a[:, 0] - 0.0, bins="auto")
|
||||
ax3b.hist(cs3b[:, 0] - 0.3, bins="auto")
|
||||
ax3c.hist(cs3c[:, 0] - (-0.3), bins="auto")
|
||||
fig3.tight_layout()
|
||||
fig3
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(centroid, np, sim):
|
||||
Dxs = []
|
||||
for p in np.linspace(-7, 7, 10):
|
||||
sms = [sim(Nphoton=1000) for m in range(100)]
|
||||
Dxs.append(np.mean([centroid(s, scale=sc)[0] - p for (s, sc) in sms]))
|
||||
return (Dxs,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Dxs, np, plt):
|
||||
fig4, ax4 = plt.subplots()
|
||||
ax4.scatter(np.linspace(-0.5, 0.5, 10), Dxs)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk5/s5.py.html
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk6/Homework6.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk6/Homework6_Solutions.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk6/cilia_movie_crop.tif
Normal file
418
courses/uoph410-510a_Image-Analysis/wk6/s6.py
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
rng = np.random.default_rng()
|
||||
return np, rng
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
plt.ion();
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from skimage import io
|
||||
import scipy.ndimage as nd
|
||||
|
||||
return (io,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import scipy as si
|
||||
import scipy.optimize as sio
|
||||
|
||||
return si, sio
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import timeit
|
||||
|
||||
return (timeit,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework6.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Cilia and temporal filtering
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
cilia_movie_crop = io.imread("cilia_movie_crop.tif", plugin="tifffile")
|
||||
cilia_movie_crop_nframes = cilia_movie_crop.shape[0]
|
||||
return cilia_movie_crop, cilia_movie_crop_nframes
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_nframes, mo):
|
||||
i = mo.ui.slider(0, cilia_movie_crop_nframes - 1, 1)
|
||||
i
|
||||
return (i,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop, i, plt):
|
||||
figi, axi = plt.subplots()
|
||||
axi.imshow(cilia_movie_crop[0,:,:], cmap="gray")
|
||||
axi.imshow(cilia_movie_crop[i.value,:,:], cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop, np):
|
||||
cilia_movie_crop_med = np.median(cilia_movie_crop, axis=0)
|
||||
return (cilia_movie_crop_med,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop, cilia_movie_crop_med, cilia_movie_crop_nframes, np):
|
||||
cilia_movie_crop_mmed = cilia_movie_crop - np.tile(cilia_movie_crop_med, (cilia_movie_crop_nframes, 1, 1))
|
||||
return (cilia_movie_crop_mmed,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_nframes, mo):
|
||||
ii = mo.ui.slider(0, cilia_movie_crop_nframes - 1, 1)
|
||||
ii
|
||||
return (ii,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop, cilia_movie_crop_mmed, ii, plt):
|
||||
figii, axii = plt.subplots()
|
||||
axii.imshow(cilia_movie_crop[0,:,:], cmap="gray")
|
||||
axii.imshow(cilia_movie_crop_mmed[ii.value,:,:], cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_mmed, plt):
|
||||
fig1, (ax1a, ax1b) = plt.subplots(2, 1)
|
||||
ax1a.imshow(cilia_movie_crop_mmed[0,:,:], cmap="gray")
|
||||
ax1b.hist(cilia_movie_crop_mmed.flatten(), bins=100) #, log=True)
|
||||
fig1
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_mmed):
|
||||
cilia_imin = -15
|
||||
cilia_imax = 15
|
||||
cilia_movie_crop_mmed_scaled = 255 * (cilia_movie_crop_mmed - cilia_imin) / (cilia_imax - cilia_imin)
|
||||
return (cilia_movie_crop_mmed_scaled,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_nframes, mo):
|
||||
iii = mo.ui.slider(0, cilia_movie_crop_nframes - 1, 1)
|
||||
iii
|
||||
return (iii,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_mmed_scaled, iii, plt):
|
||||
fig4, ax4 = plt.subplots()
|
||||
ax4.imshow(cilia_movie_crop_mmed_scaled[0,:,:], cmap="gray")
|
||||
ax4.imshow(cilia_movie_crop_mmed_scaled[iii.value,:,:], cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_mmed_scaled, np):
|
||||
cilia_movie_crop_mmed_scaled_std = np.std(cilia_movie_crop_mmed_scaled, 0)
|
||||
return (cilia_movie_crop_mmed_scaled_std,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(cilia_movie_crop_mmed_scaled_std, plt):
|
||||
fig5, ax5 = plt.subplots()
|
||||
ax5.imshow(cilia_movie_crop_mmed_scaled_std, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## MLE Practice
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def A(x0, b, x = np.linspace(-3, 4, 100)):
|
||||
return 3 * np.power(np.abs(x - x0), b) + 4
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
### Images for \#3-\#4
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, si):
|
||||
def airypsf(xy, l=0.51, NA=0.9, side=0.7, N=210):
|
||||
center = xy
|
||||
xs, ys = np.meshgrid(np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N)/2, N),
|
||||
np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N)/2, N))
|
||||
r2s = np.square(xs - center[0]) + np.square(ys - center[1])
|
||||
v = 2 * np.pi * NA * np.sqrt(r2s) / l
|
||||
psf = 4 * np.square(si.special.j1(v) / v)
|
||||
nans = np.isnan(psf)
|
||||
psf[nans] = 1
|
||||
scale = side / N
|
||||
return psf / np.sum(psf), scale
|
||||
|
||||
return (airypsf,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def pixelate(image, inscale, shape=(7, 7)):
|
||||
outscale = image.shape[0] * inscale / shape[0]
|
||||
assert image.shape[0] / image.shape[1] == shape[0] / shape[1], "Aspect Ratio must be preserved!"
|
||||
|
||||
out = np.sum(image.reshape(shape[0], int(image.shape[0] / shape[0]),
|
||||
shape[1], int(image.shape[1] / shape[1])),
|
||||
axis=(1, 3))
|
||||
|
||||
return out, outscale
|
||||
|
||||
return (pixelate,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def fishify(image, N=1, rng=np.random.default_rng()):
|
||||
return rng.poisson(lam=N * (image / np.sum(image)))
|
||||
|
||||
return (fishify,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(airypsf, fishify, np, pixelate):
|
||||
def simage4(xc, yc, N=7, Np = 1000, B=10):
|
||||
a, iscale = airypsf(np.array([xc, yc]))
|
||||
p, scale = pixelate(a, iscale, shape=(N, N))
|
||||
return fishify(p, Np) + fishify(np.ones((N, N)),N=(B * (N ** 2))), scale
|
||||
|
||||
return (simage4,)
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Centroid Localization Timing
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def centroid(im, scale=None):
|
||||
ys, xs = np.indices(im.shape)
|
||||
c = np.hstack([np.sum(xs * im), np.sum(ys * im)]) / np.sum(im)
|
||||
c = (im * np.mgrid[0:im.shape[0], 0:im.shape[1]]).sum(1).sum(1)/im.sum()
|
||||
return c if scale is None else scale * (c - np.array(im.shape) // 2)
|
||||
|
||||
return (centroid,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(centroid, rng, simage4, timeit):
|
||||
xys = list(zip(rng.uniform(-0.35, 0.35, 100), rng.uniform(-0.35, 0.35, 100)))
|
||||
ims = [simage4(x, y)[0] for x, y in xys]
|
||||
startt = timeit.default_timer()
|
||||
cs = [centroid(i) for i in ims]
|
||||
print(timeit.default_timer() - startt, "seconds")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Gaussian MLE for particle localization!
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, simage4):
|
||||
fig2, ax2 = plt.subplots()
|
||||
im, sc = simage4(-0.08, 0.03)
|
||||
ax2.imshow(im)
|
||||
return (im,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(airypsf, np, pixelate):
|
||||
def objcam(params, im, l, NA, side):
|
||||
x, y = params
|
||||
p, s = airypsf(np.array([x, y]), l=l, NA=NA, side=side)
|
||||
A, _ = pixelate(p, s, shape=im.shape)
|
||||
|
||||
mlogp = np.sum(A - im * np.log(A))
|
||||
return mlogp
|
||||
|
||||
return (objcam,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, objcam, sio):
|
||||
def MLElocalize_knowcam(im, l=0.51, NA=0.9, side=0.7, guess=np.array([-0.05, 0.1])):
|
||||
bnd = ((-side / 2, side / 2), (-side / 2, side / 2))
|
||||
res = sio.minimize(objcam, guess, args=(im, l, NA, side), bounds= bnd)
|
||||
return res
|
||||
|
||||
return (MLElocalize_knowcam,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MLElocalize_knowcam, im):
|
||||
MLElocalize_knowcam(im)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def gausspsf(xc, yc, A0, s, B, N=210, side=0.7):
|
||||
xs = np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N) / 2, N)
|
||||
ys = np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N) / 2, N)
|
||||
xx, yy = np.meshgrid(xs, ys)
|
||||
g = A0 * np.exp(-(np.square(xx - xc) + np.square(yy - yc)) / (2.0 * np.square(s))) + B
|
||||
return g, (side / N)
|
||||
|
||||
return (gausspsf,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gausspsf, pixelate, plt):
|
||||
fig3, ax3 = plt.subplots()
|
||||
im3, sc3 = gausspsf(0, 0, 0.02, 0.1, 1) # initial guess
|
||||
im3p, _ = pixelate(im3, sc3, shape=(7, 7))
|
||||
ax3.imshow(im3p)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gausspsf, np):
|
||||
def objgauss(params, im, side):
|
||||
xc, yc, A0, s, B = params
|
||||
p, sc = gausspsf(xc, yc, A0, s, B, side=side, N=im.shape[0])
|
||||
#A, _ = pixelate(p, sc, shape=im.shape)
|
||||
|
||||
mlogp = np.sum(p - im * np.log(p))
|
||||
#mlogp = np.sum(A - im * np.log(A))
|
||||
return mlogp
|
||||
|
||||
return (objgauss,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, objgauss, sio):
|
||||
def MLElocalize_gauss(im, side=0.7, guess=None):
|
||||
if guess is None:
|
||||
guess = np.array([0, 0, np.max(im), 0.1, np.min(im)])
|
||||
bnd = ((-side / 2, side / 2), (-side / 2, side / 2), (0, np.max(im)), (1e-2, None), (0, None))
|
||||
res = sio.minimize(objgauss, guess, args = (im, side), bounds= bnd)
|
||||
return res
|
||||
|
||||
return (MLElocalize_gauss,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MLElocalize_gauss, im):
|
||||
res = MLElocalize_gauss(im)
|
||||
res
|
||||
return (res,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gausspsf, plt, res):
|
||||
fig8, ax8 = plt.subplots()
|
||||
im8, _ = gausspsf(*res.x, side=0.7, N=7)
|
||||
ax8.imshow(im8)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MLElocalize_gauss, simage4):
|
||||
resx = []
|
||||
for _ in range(100):
|
||||
im9, sc9 = simage4(0.03, 0.03)
|
||||
res9 = MLElocalize_gauss(im9)
|
||||
resx.append(res9.x[0] - 0.03)
|
||||
return (resx,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, resx):
|
||||
figh, axh = plt.subplots()
|
||||
axh.hist(resx, bins="auto")
|
||||
figh
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MLElocalize_gauss, np, plt, simage4):
|
||||
figs, axs = plt.subplots()
|
||||
xs = np.linspace(-0.05, 0.05, 10)
|
||||
ys = np.zeros(10)
|
||||
imss = [simage4(xs[i], ys[i])[0] for i in range(10)]
|
||||
es = [MLElocalize_gauss(image).x[0] for image in imss]
|
||||
axs.scatter(xs, es - xs)
|
||||
#axs.set_ylim([-0.5, 0.5])
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MLElocalize_gauss, np, plt, rng, simage4):
|
||||
figr, axr = plt.subplots()
|
||||
xss = rng.uniform(-0.5 * 0.1, 0.5 * 0.1, 100)
|
||||
yss = rng.uniform(-0.5 * 0.1, 0.5 * 0.1, 100)
|
||||
imsss = [simage4(xss[i], yss[i])[0] for i in range(100)]
|
||||
ess = np.array([MLElocalize_gauss(image).x[0] for image in imsss])
|
||||
axr.scatter(xss, ess - xss)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk6/s6.py.html
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk7/Homework7.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk7/Homework7_Solutions.pdf
Normal file
|
After Width: | Height: | Size: 273 KiB |
|
|
@ -0,0 +1,133 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# radialcenter_ImAnClass.py
|
||||
"""
|
||||
Author: Raghuveer Parthasarathy
|
||||
Created on Mon Oct 31 13:33:05 2022
|
||||
Last modified on Mon Oct 31 13:33:05 2022
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Particle localization by radial symmetry
|
||||
Python translation of MATLAB radialcenter.m
|
||||
|
||||
** Version for Image Analysis Class**
|
||||
Same as radialcenter.py , but with sigma and meand2 outputs removed,
|
||||
and output positions returned relative to image center.
|
||||
|
||||
Uses 0 indexing of positions (unlike MATLAB)
|
||||
NOTE: *Does not* optimize for image stacks (like radialcenter_stk.m);
|
||||
just single image
|
||||
|
||||
Copyright 2011-2022, Raghuveer Parthasarathy, The University of Oregon
|
||||
|
||||
Calculates the center of a 2D intensity distribution.
|
||||
Method: Considers lines passing through each half-pixel point with slope
|
||||
parallel to the gradient of the intensity at that point. Considers the
|
||||
distance of closest approach between these lines and the coordinate
|
||||
origin, and determines (analytically) the origin that minimizes the
|
||||
weighted sum of these distances-squared.
|
||||
Applies simple smoothing if size > 3x3
|
||||
|
||||
Inputs
|
||||
I : 2D intensity distribution (i.e. a grayscale image)
|
||||
Size need not be an odd number of pixels along each dimension
|
||||
|
||||
Outputs
|
||||
xc, yc : the center of radial symmetry, px, relative to image center
|
||||
Note that y increases with increasing row number (i.e. "downward")
|
||||
|
||||
To do:
|
||||
- Test more (like MATLAB version)
|
||||
- Faster grid creation than meshgrid? (like in MATLAB code)
|
||||
|
||||
see notes August 19-25, Sept. 9, Sept. 19-20 2011
|
||||
Raghuveer Parthasarathy
|
||||
The University of Oregon
|
||||
August 21, 2011 (begun)
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np # Will assume numpy is already imported as np !
|
||||
|
||||
|
||||
def radialcenter(I):
|
||||
# The main function -- see header comments for details
|
||||
|
||||
(Ny, Nx) = I.shape
|
||||
# grid coordinates are -n:n, where Nx (or Ny) = 2*n+1
|
||||
# grid midpoint coordinates are -n+0.5:n-0.5
|
||||
xm, ym = np.meshgrid(np.arange(-(Nx-1)/2.0 + 0.5, (Nx-1)/2.0+0.5),
|
||||
np.arange(-(Ny-1)/2.0 + 0.5, (Ny-1)/2.0+0.5))
|
||||
# Calculate derivatives along 45-degree shifted coordinates (u and v)
|
||||
# Note that y increases "downward" (increasing row number) -- we'll deal
|
||||
# with this when calculating "m" below.
|
||||
dIdu = I[0:Ny-1,1:]-I[1:,0:Nx-1]
|
||||
dIdv = I[0:Ny-1,0:Nx-1]-I[1:,1:]
|
||||
# Smoothing -- perhaps should be optional
|
||||
fdu = dIdu # will overwrite if smoothing
|
||||
fdv = dIdv
|
||||
if np.min((Nx, Ny))>3:
|
||||
# Only smooth if image is >3px in the smallest dimension
|
||||
# Smooth by simple 3x3 boxcar, which I'll code directly rather than
|
||||
# calling a convolution.
|
||||
# Zero-pad (expand by 1 on each side)
|
||||
dIdu_pad = np.zeros((Ny+1,Nx+1)) # dIdu array is size Ny-1, Nx-1
|
||||
dIdv_pad = np.zeros((Ny+1,Nx+1)) # dIdv array is size Ny-1, Nx-1
|
||||
dIdu_pad[1:Ny, 1:Nx] = dIdu
|
||||
dIdv_pad[1:Ny, 1:Nx] = dIdv
|
||||
fdu = np.zeros_like(dIdu)
|
||||
fdv = np.zeros_like(dIdv)
|
||||
for j in range(Ny-1):
|
||||
for k in range(Nx-1):
|
||||
fdu[j,k] = np.mean(dIdu_pad[j:j+3,k:k+3])
|
||||
fdv[j,k] = np.mean(dIdv_pad[j:j+3,k:k+3])
|
||||
dImag2 = fdu*fdu + fdv*fdv # gradient magnitude, squared
|
||||
|
||||
# Slope of the gradient . Note that we need a 45 degree rotation of
|
||||
# the u,v components to express the slope in the x-y coordinate system.
|
||||
# The negative sign "flips" the array to account for y increasing
|
||||
# "downward"
|
||||
m = -(fdv + fdu) / (fdu-fdv)
|
||||
# Not smoothed version: m = -(dIdv + dIdu) ./ (dIdu-dIdv)
|
||||
|
||||
infslope = 9e9 #replace infinite slope values with this extremely large number
|
||||
m[np.isinf(m)] = infslope
|
||||
|
||||
# Shorthand "b", which also happens to be the
|
||||
# y intercept of the line of slope m that goes through each grid midpoint
|
||||
b = ym - m*xm
|
||||
|
||||
# Weighting: weight by square of gradient magnitude and inverse
|
||||
# distance to gradient intensity centroid.
|
||||
sdI2 = np.sum(dImag2)
|
||||
xcentroid = np.sum(dImag2*xm)/sdI2
|
||||
ycentroid = np.sum(dImag2*ym)/sdI2
|
||||
w = dImag2/np.sqrt((xm-xcentroid)*(xm-xcentroid) +
|
||||
(ym-ycentroid)*(ym-ycentroid))
|
||||
|
||||
# if the intensity is completely flat, m will be NaN (0/0)
|
||||
# give these points zero weight (and set m, b = 0 to avoid 0*NaN=NaN)
|
||||
w[np.isnan(m)]=0
|
||||
b[np.isnan(m)]=0
|
||||
m[np.isnan(m)]=0
|
||||
|
||||
# least-squares minimization to determine the translated coordinate
|
||||
# system origin (xc, yc) such that lines y = mx+b have
|
||||
# the minimal total distance^2 to the origin:
|
||||
# Unilke the MATLAB version, where I have a separate function
|
||||
# for this (lsradialcenterfit), I'll just write the calculation here:
|
||||
# Note m, b, w are defined on a grid; w are the weights for each point
|
||||
wm2p1 = w/(m*m+1)
|
||||
sw = np.sum(wm2p1)
|
||||
smmw = np.sum(m*m*wm2p1)
|
||||
smw = np.sum(m*wm2p1)
|
||||
smbw = np.sum(m*b*wm2p1)
|
||||
sbw = np.sum(b*wm2p1)
|
||||
det = smw*smw - smmw*sw
|
||||
xc = (smbw*sw - smw*sbw)/det # relative to image center
|
||||
yc = (smbw*smw - smmw*sbw)/det # relative to image center
|
||||
|
||||
|
||||
return xc, yc
|
||||
|
||||
362
courses/uoph410-510a_Image-Analysis/wk7/s7.py
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
rng = np.random.default_rng()
|
||||
return np, rng
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
plt.ion();
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from skimage import io, restoration
|
||||
import scipy.ndimage as nd
|
||||
|
||||
return io, nd, restoration
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import scipy as si
|
||||
import scipy.optimize as sio
|
||||
|
||||
return si, sio
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import timeit
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework7.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Gaussian MLE and number of photons
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, si):
|
||||
def airypsf(xy, l=0.51, NA=0.9, side=0.7, N=210):
|
||||
center = xy
|
||||
xs, ys = np.meshgrid(np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N)/2, N),
|
||||
np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N)/2, N))
|
||||
r2s = np.square(xs - center[0]) + np.square(ys - center[1])
|
||||
v = 2 * np.pi * NA * np.sqrt(r2s) / l
|
||||
psf = 4 * np.square(si.special.j1(v) / v)
|
||||
nans = np.isnan(psf)
|
||||
psf[nans] = 1
|
||||
scale = side / N
|
||||
return psf / np.sum(psf), scale
|
||||
|
||||
return (airypsf,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def pixelate(image, inscale, shape=(7, 7)):
|
||||
outscale = image.shape[0] * inscale / shape[0]
|
||||
assert image.shape[0] / image.shape[1] == shape[0] / shape[1], "Aspect Ratio must be preserved!"
|
||||
|
||||
out = np.sum(image.reshape(shape[0], int(image.shape[0] / shape[0]),
|
||||
shape[1], int(image.shape[1] / shape[1])),
|
||||
axis=(1, 3))
|
||||
|
||||
return out, outscale
|
||||
|
||||
return (pixelate,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def fishify(image, N=1, rng=np.random.default_rng()):
|
||||
return rng.poisson(lam=N * (image / np.sum(image)))
|
||||
|
||||
return (fishify,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(airypsf, fishify, np, pixelate):
|
||||
def simage4(xc, yc, N=7, Np = 1000, B=10):
|
||||
a, iscale = airypsf(np.array([xc, yc]))
|
||||
p, scale = pixelate(a, iscale, shape=(N, N))
|
||||
return fishify(p, Np) + fishify(np.ones((N, N)),N=(B * (N ** 2))), scale
|
||||
|
||||
return (simage4,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def gausspsf(xc, yc, A0, s, B, N=210, side=0.7):
|
||||
xs = np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N) / 2, N)
|
||||
ys = np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N) / 2, N)
|
||||
xx, yy = np.meshgrid(xs, ys)
|
||||
g = A0 * np.exp(-(np.square(xx - xc) + np.square(yy - yc)) / (2.0 * np.square(s))) + B
|
||||
return g, (side / N)
|
||||
|
||||
return (gausspsf,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gausspsf, np):
|
||||
def objgauss(params, im, side):
|
||||
xc, yc, A0, s, B = params
|
||||
p, sc = gausspsf(xc, yc, A0, s, B, side=side, N=im.shape[0])
|
||||
#A, _ = pixelate(p, sc, shape=im.shape)
|
||||
|
||||
mlogp = np.sum(p - im * np.log(p))
|
||||
#mlogp = np.sum(A - im * np.log(A))
|
||||
return mlogp
|
||||
|
||||
return (objgauss,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np, objgauss, sio):
|
||||
def MLElocalize_gauss(im, side=0.7, guess=None):
|
||||
if guess is None:
|
||||
guess = np.array([0, 0, np.max(im), 0.1, np.min(im)])
|
||||
bnd = ((-side / 2, side / 2), (-side / 2, side / 2), (0, np.max(im)), (1e-2, None), (0, None))
|
||||
res = sio.minimize(objgauss, guess, args = (im, side), bounds= bnd)
|
||||
return res
|
||||
|
||||
return (MLElocalize_gauss,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
### a.
|
||||
See solution from last week! Looks unbiased:
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MLElocalize_gauss, np, plt, rng, simage4):
|
||||
figr, axr = plt.subplots()
|
||||
xs = rng.uniform(-0.5 * 0.1, 0.5 * 0.1, 100)
|
||||
ys = rng.uniform(-0.5 * 0.1, 0.5 * 0.1, 100)
|
||||
ims = [simage4(xs[i], ys[i])[0] for i in range(100)]
|
||||
es = np.array([MLElocalize_gauss(image).x[0] for image in ims])
|
||||
axr.scatter(xs, es - xs)
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
### b.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def RMSE(xs, ts=None):
|
||||
if ts is None:
|
||||
ts = np.zeros_like(xs)
|
||||
return np.sqrt(np.mean(np.square(xs - ts), axis=1))
|
||||
|
||||
return (RMSE,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(MLElocalize_gauss, np, simage4):
|
||||
Nps = np.logspace(1, 5, 30)
|
||||
imss = [simage4(0, 0, Np=i)[0] for i in Nps]
|
||||
ess = np.array([MLElocalize_gauss(image).x for image in imss])[:,0:2]
|
||||
return Nps, ess
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Nps, RMSE, ess, np, plt):
|
||||
fig2, ax2 = plt.subplots()
|
||||
ax2.loglog(Nps, RMSE(ess))
|
||||
ax2.loglog(Nps, 0.51 / 2 / 0.9 / np.sqrt(Nps)) # theoretical baseline
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
TODO: Need to RMSE over multiple samples for each Np, not just one like this, but trend is already looking on-point.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Radial-symmetry-based particle localization
|
||||
TODO: Mostly running Prof. code.
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Assessing Deconvolution
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def gausspsff(xc, yc, A0, s, B, N=210, side=0.7):
|
||||
xs = np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N) / 2, N)
|
||||
ys = np.linspace(- side * (1 - 1/N) / 2, side * (1 - 1/N) / 2, N)
|
||||
xx, yy = np.meshgrid(xs, ys)
|
||||
g = A0 * np.exp(-(np.square(xx - xc) + np.square(yy - yc)) / (2.0 * np.square(s))) + B
|
||||
return g / np.sum(g), (side / N)
|
||||
|
||||
return (gausspsff,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(np):
|
||||
def fishifyf(image, N=1, rng=np.random.default_rng()):
|
||||
return rng.poisson(lam=N * (image / np.sum(image)))
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gausspsff, plt):
|
||||
fig, ax = plt.subplots()
|
||||
gpsf = gausspsff(0, 0, 1, 7, 0, 35, 35)[0]
|
||||
gpsf2 = gausspsff(0, 0, 1, 5, 0, 35, 35)[0]
|
||||
ax.imshow(gpsf)
|
||||
return (gpsf,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io):
|
||||
mouse_glial_cells_crop_png = io.imread("mouse_glial_cells_RBurdan_crop.png", as_gray=True)
|
||||
return (mouse_glial_cells_crop_png,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mouse_glial_cells_crop_png, plt):
|
||||
fig3, ax3 = plt.subplots()
|
||||
ax3.imshow(mouse_glial_cells_crop_png, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gpsf, mouse_glial_cells_crop_png, nd):
|
||||
mouse_glial_cells_crop_conv = nd.convolve(mouse_glial_cells_crop_png, gpsf, mode="constant")
|
||||
return (mouse_glial_cells_crop_conv,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mouse_glial_cells_crop_conv, plt):
|
||||
fig4, ax4 = plt.subplots()
|
||||
ax4.imshow(mouse_glial_cells_crop_conv, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mouse_glial_cells_crop_conv, rng):
|
||||
mouse_glial_cells_crop_fish = rng.poisson(mouse_glial_cells_crop_conv)
|
||||
return (mouse_glial_cells_crop_fish,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mouse_glial_cells_crop_fish, plt):
|
||||
fig5, ax5 = plt.subplots()
|
||||
ax5.imshow(mouse_glial_cells_crop_fish, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(gpsf, mouse_glial_cells_crop_fish, restoration):
|
||||
mouse_glial_cells_crop_restored = restoration.richardson_lucy(mouse_glial_cells_crop_fish, gpsf, num_iter=20, clip=False)
|
||||
return (mouse_glial_cells_crop_restored,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mouse_glial_cells_crop_restored, plt):
|
||||
fig6, ax6 = plt.subplots()
|
||||
ax6.imshow(mouse_glial_cells_crop_restored, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
gpsf,
|
||||
mouse_glial_cells_crop_fish,
|
||||
mouse_glial_cells_crop_png,
|
||||
np,
|
||||
restoration,
|
||||
):
|
||||
rmss = []
|
||||
imsi = []
|
||||
for i in range(1, 250, 10):
|
||||
mouse_glial_cells_crop_restorei = restoration.richardson_lucy(mouse_glial_cells_crop_fish, gpsf, num_iter=i, clip=False)
|
||||
mouse_glial_cells_crop_restorei = mouse_glial_cells_crop_restorei[35:-35, 35:-35]
|
||||
mouse_glial_cells_crop_restorei -= np.min(mouse_glial_cells_crop_restorei)
|
||||
mouse_glial_cells_crop_restorei *= (np.max(mouse_glial_cells_crop_png[35:-35, 35:-35]) - np.min(mouse_glial_cells_crop_png[35:-35, 35:-35])) / np.max(mouse_glial_cells_crop_restorei)
|
||||
mouse_glial_cells_crop_restorei += np.min(mouse_glial_cells_crop_png[35:-35, 35:-35])
|
||||
imsi.append(mouse_glial_cells_crop_restorei)
|
||||
rms = np.sqrt(np.mean(np.square(mouse_glial_cells_crop_restorei - mouse_glial_cells_crop_png[35:-35, 35:-35])))
|
||||
rmss.append(rms)
|
||||
return imsi, rmss
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(plt, rmss):
|
||||
fig7, ax7 = plt.subplots()
|
||||
ax7.scatter(range(1, 250, 10), rmss)
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(imsi, np, plt, rmss):
|
||||
fig8, ax8 = plt.subplots()
|
||||
ax8.imshow(imsi[np.argmin(rmss)], cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
293
courses/uoph410-510a_Image-Analysis/wk7/s7.py.html
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk8/Homework8.pdf
Normal file
BIN
courses/uoph410-510a_Image-Analysis/wk8/Homework8_Solutions.pdf
Normal file
|
After Width: | Height: | Size: 1 MiB |
|
After Width: | Height: | Size: 372 KiB |
88
courses/uoph410-510a_Image-Analysis/wk8/s8.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import marimo
|
||||
|
||||
__generated_with = "0.19.11"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import numpy as np
|
||||
rng = np.random.default_rng()
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import scipy as si
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
from skimage import io, morphology as mf
|
||||
|
||||
return io, mf
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
plt.ion();
|
||||
return (plt,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
from pathlib import Path
|
||||
mo.pdf(src=Path("Homework8.pdf"), width="100%", height="50vh")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""
|
||||
## Spot Removal
|
||||
""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(io, plt):
|
||||
lichtenstein_imageduplicator_1963_png = io.imread("Lichtenstein_imageDuplicator_1963.png")
|
||||
lichtenstein_imageduplicator_1963_gray = io.imread("Lichtenstein_imageDuplicator_1963_gray.png")
|
||||
fig0, (ax0a, ax0b) = plt.subplots(1, 2)
|
||||
ax0a.imshow(lichtenstein_imageduplicator_1963_png)
|
||||
ax0b.imshow(lichtenstein_imageduplicator_1963_gray, cmap="gray")
|
||||
return (lichtenstein_imageduplicator_1963_gray,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(lichtenstein_imageduplicator_1963_gray, mf):
|
||||
lichtenstein_imageduplicator_1963_close = mf.closing(lichtenstein_imageduplicator_1963_gray, mf.disk(4))
|
||||
lichtenstein_imageduplicator_1963_close = mf.closing(lichtenstein_imageduplicator_1963_gray, mf.disk(2))
|
||||
return (lichtenstein_imageduplicator_1963_close,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(lichtenstein_imageduplicator_1963_close, plt):
|
||||
fig1, ax1 = plt.subplots()
|
||||
ax1.imshow(lichtenstein_imageduplicator_1963_close, cmap="gray")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||