如何在Python3的OpenCV中实现Pinetools网站的Glow发光滤镜效果?
Implementing Pinetools' Glow Effect with Python & OpenCV
Hey there, let's figure out how to replicate that glow effect from Pinetools using Python and OpenCV, based on the Pixastic JavaScript algorithm you're referencing.
First, let's break down what the original JS code actually does—this is why your current attempt isn't matching the expected result:
- Step 1: Apply a Gaussian blur to the original image (the blur intensity is set by the
blurAmountparameter) - Step 2: Brighten the blurred image to make that soft, glowing area stand out (controlled by the
brightnessvalue) - Step 3: Overlay this brightened blur onto the original image using the Screen blend mode (with an
opacityparameter to adjust how strong the glow feels)
Your current code only tweaks channel brightness on the blurred image and concatenates it to the original, missing the critical blending step that makes the glow look natural. Here's the full working implementation:
Full Working Code
import cv2 import numpy as np def apply_glow(image_path, blur_amount=4, brightness=100, opacity=0.7): # Load the image (OpenCV uses BGR format by default) original = cv2.imread(image_path, cv2.IMREAD_COLOR) if original is None: raise ValueError("Couldn't load the image—double-check your file path!") # Step 1: Apply Gaussian Blur # We use an odd-sized kernel matching the blur amount (matches Pixastic's behavior) kernel_size = (blur_amount * 2 + 1, blur_amount * 2 + 1) blurred = cv2.GaussianBlur(original, kernel_size, sigmaX=0) # Auto-calculate sigma # Step 2: Brighten the blurred image safely # Using convertScaleAbs avoids pixel value overflow issues brightened_blur = cv2.convertScaleAbs(blurred, alpha=1, beta=brightness) # Step 3: Screen Blend Mode + Opacity # Convert images to 0-1 float range for calculations original_float = original.astype(np.float32) / 255.0 brightened_float = brightened_blur.astype(np.float32) / 255.0 # Screen blend formula: result = 1 - (1 - src1) * (1 - src2) screen_blend = 1 - (1 - original_float) * (1 - brightened_float) # Mix with original using opacity: original*(1-opacity) + blended*(opacity) result_float = (original_float * (1 - opacity)) + (screen_blend * opacity) # Convert back to 8-bit unsigned integer (0-255) result = (result_float * 255).astype(np.uint8) return original, result # Example usage if __name__ == "__main__": IMAGE_PATH = "your_image_file.jpg" # Replace with your image path original_img, glow_img = apply_glow(IMAGE_PATH, blur_amount=4, brightness=100, opacity=0.7) # Show original vs side-by-side with glow effect side_by_side = np.concatenate((original_img, glow_img), axis=1) cv2.imshow("Original vs Glow Effect", side_by_side) cv2.waitKey(0) cv2.destroyAllWindows() # Save the result if needed cv2.imwrite("glow_effect_result.jpg", glow_img)
Key Details Explained
- Gaussian Blur: We use a kernel size tied to
blur_amountto match how the JS algorithm handles blur intensity—this ensures the soft glow spreads the right amount. - Safe Brightening:
cv2.convertScaleAbsautomatically clamps pixel values to 0-255, which is way more reliable than manually checking for overflow like your original code did. - Screen Blend Mode: This is the magic behind the glow! Screen blending makes bright areas brighter while preserving dark details from the original image, just like the Pinetools effect.
- Opacity Control: The
opacityparameter lets you dial the glow up or down—higher values make the glow more intense, lower values keep it subtle.
What Was Missing in Your Original Code?
- You didn't blend the brightened blur back onto the original image—this is the core step that creates the glowing effect instead of just showing a separate bright blur.
- Your code adjusted red, green, and blue channels by different amounts, but glow effects should brighten all channels evenly for a natural look.
- Manual overflow checks (like
r_n.any() >255) don't work as intended—they set the entire channel to 255 if any pixel exceeds it, instead of clamping individual pixels.
Tweak the blur_amount, brightness, and opacity parameters to match exactly what you see on Pinetools!
内容的提问来源于stack exchange,提问作者Arnand




