Home

Search John Harvey Photo for...
Advanced Search...
Photo Search Returned 1 to 6 of 6
Restrict search - underwater AND sea urchin AND: Vietnam 2 BC fauna 1 time lapse 1
New search - Related Tags: BC fauna 159 Vietnam 131 time lapse 71

Ogden Point Urchins
This is 66 images. Stabilization was done with a python script:
import cv2 
import numpy as np
import matplotlib.pyplot as plt
import pprint
import math


# /opt/homebrew/bin/ffmpeg -framerate 30 -pattern_type glob -i '*_EurchinsHg.jpg' -c:v libx264 -crf 20 EurchinsHg.mp4
# /opt/homebrew/bin/ffmpeg -i EurchinsHg.mp4 -vf "vidstabtransform=input=transforms.trf" -crf 20 EurchinsStabilized.mp4


def replace_color_with_image(background, overlay, target_color, tolerance, output_path):
    """
    Replaces a specific color in an image with another image.

    Args:
        background_path (str): Path to the background image.
        overlay_path (str): Path to the overlay image (can be the same as background if no overlay needed).
        target_color (tuple): RGB color to replace (e.g., (255, 0, 0) for red).
        tolerance (int): Tolerance range for color matching.
        replacement_image_path (str): Path to the replacement image.
        output_path (str): Path to save the output image.
    """
    if background is None or overlay is None:
        raise FileNotFoundError("One or more images not found.")

    # Create a mask for the target color
    lower_bound = np.array([max(0, c - tolerance) for c in target_color], dtype="uint8")
    upper_bound = np.array([min(255, c + tolerance) for c in target_color], dtype="uint8")
    mask = cv2.inRange(overlay, lower_bound, upper_bound)

    kernel = np.ones((3, 3), np.uint8) 
    dialated_mask = cv2.dilate(mask, kernel, iterations=1) 

    mask_rgb = cv2.merge((dialated_mask,dialated_mask,dialated_mask))

    mask_inv = cv2.bitwise_not(dialated_mask)
    mask_inv_rgb = cv2.merge((mask_inv,mask_inv,mask_inv))

    masked_background = cv2.bitwise_and(mask_rgb, background) # pixels from background where target_color is in the overlay.
    masked_overlay = cv2.bitwise_and(mask_inv_rgb, overlay) # pixels from background where target_color is in the overlay.
    combined = cv2.add(masked_background, masked_overlay)


    cv2.imwrite(output_path, combined)



f = open("transforms.trf", "w")
f.write("VID.STAB 1")
f.write("#      accuracy = 15")
f.write("#     shakiness = 3")
f.write("#      stepsize = 4")
f.write("#   mincontrast = 0.200000")
f.write("Frame 1 (List 0 [])
")

img1 = cv2.imread('0012_EurchinsHg.jpg')  
mask = cv2.imread('mask.png', cv2.IMREAD_GRAYSCALE)

currentMask = mask

#sift
sift = cv2.SIFT_create()

keypoints_1, descriptors_1 = sift.detectAndCompute(img1,mask)

for n in range(1,67): # Remember to +1 the end number.
    print("Frame " + str(n))
    img2 = cv2.imread("{:04d}_EurchinsHg.jpg".format(n)) 
    #img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

    keypoints_2, descriptors_2 = sift.detectAndCompute(img2,currentMask)

    #feature matching
    bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)

    matches = bf.match(descriptors_1,descriptors_2)
    matches = sorted(matches, key = lambda x:x.distance)

    # Get key points
    points1 = np.float32([keypoints_1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)
    points2 = np.float32([keypoints_2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)

    # Affine matrix
    matrix, _ = cv2.findHomography(points2, points1, cv2.RANSAC, ransacReprojThreshold=5.0)


    # Align
    new_background_color = (0, 255, 0)  # Green

    aligned_image = cv2.warpPerspective(img2, matrix, (img1.shape[1], img1.shape[0]), borderValue=new_background_color)

    replace_color_with_image(img1, aligned_image, new_background_color, 1, "aligned_{:04d}_EurchinsHg.jpg".format(n))


f.close()
The actual stabilization is done with ffmpeg:
/opt/homebrew/bin/ffmpeg -framerate 30 -pattern_type glob -i 'aligned_*_EurchinsHg.jpg' -c:v libx264 -crf 20 AlignedEurchinsHg.mp4
Species: Strongylocentrotus droebachiensis (Green Sea Urchin), Strongylocentrotus purpuratus (Purple Sea Urchin)

John Harvey Photo > Ogden Point Urchins

Green Sea Eurchins
This is what happens when you turn the flash on.
Species: Strongylocentrotus droebachiensis (Green Sea Urchin)

John Harvey Photo > John's Overnight Page > Desolation Sound > Green Sea Eurchins

Sea Urchin Barrens
The Sea Urchins used to be kept in check by sea otters. Now there are so many they have eaten almost all of their primary food (kelp) on the lower parts of the bottom. The Sea Urchins now come out of the water to eat the highest growing kelps.
Species: Strongylocentrotus franciscanus (Red Sea Urchin)

John Harvey Photo > John's Overnight Page > Haida Gwaii > Tanu > Sea Urchin Barrens

Blood Star With Purple Sea Urchins
I'm surprised to see the purple sea urchins out like this - I'm used to them tightly packed into cracks in the rocks.
Species: Henricia leviuscula (Blood Star), Strongylocentrotus purpuratus (Purple Sea Urchin)

John Harvey Photo > John's Overnight Page > Haida Gwaii > SGang Gwaay > Blood Star With Purple Sea Urchins

Swimming Over Spikes
Swimming Over Spikes
John Harvey Photo > Trips out of the Country > Vietnam > Pho Quoc > Swimming Over Spikes

Sea Urchins Grazing
I'm pretty sure this is Diadema Genius. I'm less sure about setosum but it does match what I'm seeing on the internet. At the time, I thought these were feeding on the coral but from what I've read, they feed on algae.
Species: Diadema setosum (Setosum Spined Urchin)

John Harvey Photo > Trips out of the Country > Vietnam > Pho Quoc > Sea Urchins Grazing