How to Estimate Visibility Using Atmospheric Tower Photos

This article explains a step‑by‑step method for measuring atmospheric visibility by annotating landmarks in fixed‑angle tower photos, extracting their pixel regions, scoring recognizability with a standard‑deviation‑based metric, and computing the farthest visible object using Python and OpenCV.

Caiyun Tech Team
Caiyun Tech Team
Caiyun Tech Team
How to Estimate Visibility Using Atmospheric Tower Photos

Fixed‑angle photos from the Chinese Academy of Atmospheric Physics 325 m meteorological tower are used to estimate visibility.

Atmospheric Tower and Camera Setup

The tower is located at 39°58′N, 116°22′E, 49 m above sea level. Two 24‑hour HD cameras are mounted at 280 m height, each capturing an image every half hour. The northeast‑facing camera is selected because the southwest camera often suffers from over‑exposure.

Landmark Distance Measurement

Landmarks visible in the tower photos are located in Google Earth using the tower’s known coordinates. Satellite imagery is manually aligned with the tower photo, and the Google Earth distance tool measures the distance from the tower to each landmark. The pixel coordinates of the landmark bounding boxes and the measured distances are stored in a config.json file, for example:

{
    "Huating Jiayuan": {"x1": 896, "y1": 2285, "x2": 3154, "y2": 3246, "distance": 1.27},
    "Water Cube": {"x1": 2420, "y1": 1886, "x2": 3524, "y2": 2191, "distance": 2.18},
    "Pangu Grand View": {"x1": 1691, "y1": 1079, "x2": 2385, "y2": 2104, "distance": 1.71}
    // ... additional entries omitted for brevity
}

Cropping Landmark Regions

Using the coordinates from config.json, each landmark region is cropped from the original photo:

import cv2

def crop_image(x1, y1, x2, y2, image_path, output_path):
    img = cv2.imread(image_path)
    cropped_img = img[y1:y2, x1:x2]
    cv2.imwrite(output_path, cropped_img)

Recognizability Scoring

Visibility is inferred from the recognizability of each landmark. The recognizability score is defined as the product of the image’s standard deviation (SD) and its spectral width (max − min) after converting the image to grayscale. Higher scores indicate clearer, more recognizable scenes.

import matplotlib.pyplot as plt

def is_clear(image_fp, threshold=250):
    image = (plt.imread(image_fp) * 255).astype("uint8")
    std = image.std()
    span = image.max() - image.min()
    score = std * span
    return score > threshold

Empirical observation shows scores below 200 correspond to indistinguishable landmarks; a threshold of 250 is used to classify a landmark as “visible”.

Computing Full‑Image Visibility

After classifying each landmark, the farthest “visible” landmark determines the overall visibility distance. The implementation loads the configuration, crops each landmark, applies the recognizability test, collects distances of visible landmarks, and returns the maximum distance rounded to the nearest kilometre.

import os, json, shutil

CONFIG_FP = os.path.join(os.path.dirname(__file__), "config.json")

def get_config(config_fp=CONFIG_FP):
    with open(config_fp) as f:
        return json.load(f)

def analysis_visibility(image_fp, threshold=250, tmpdir="./tmp", keep_tmp=False):
    config = get_config()
    visibles = []
    for key, value in config.items():
        x1, y1, x2, y2 = value["x1"], value["y1"], value["x2"], value["y2"]
        distance = value["distance"]
        savefp = os.path.join(tmpdir, f"{key}.jpg")
        os.makedirs(tmpdir, exist_ok=True)
        crop_image(x1, y1, x2, y2, image_fp, savefp)
        if is_clear(savefp, threshold):
            visibles.append(distance)
    if not keep_tmp:
        shutil.rmtree(tmpdir)
    return round(max(visibles), 0)

The function analysis_visibility thus provides a one‑click visibility estimate for any tower photo.

Demo Results

Applying the pipeline to several real‑world tower images yields visibility distances that match visual expectations.

Source code is open‑sourced at https://github.com/caiyunapp/tower-eye/tree/main.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

computer visionPythonimage processingOpenCVvisibility detectionatmospheric tower
Caiyun Tech Team
Written by

Caiyun Tech Team

Engineering

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.