Last week, my friend little star shared his new beautiful deep space photo:
These spikes created by his 3000mm telescope, which are rare in the normal camera lens. So I want to fake them by post processing.
After some googling, there is already one photoshop filter, called Starspikes Pro by ProDigital Software, it creates almost same effects:
However, it only supports windows, but I only use Mac & linux…So I need to create this filter by myself.
The basic logic
Here is my test image, using a normal Tarmon 70–300mm lens, no star spikes:
And we need to install the basic python library for image processing:
pip install python-opencv
First at all, we need to find stars in the dark sky. In the starry sky, they are high lights spots. For normal RGB image, we should convert it to black & white first, then only select the high light part, whose brightness is over a threshold, for example: 200:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)thresh = cv2.threshold(gray, threshold, 255, cv2.THRESH_BINARY)[1]
After this conversion, you got this B & W image:
Then, we should know the location and size of the high light spot. I use opencv’s findContours function(from API documentation):
findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy@brief Finds contours in a binary image.The function retrieves contours from the binary image using the algorithm @cite Suzuki85 . The contours are a useful tool for shape analysis and object detection and recognition.
This function find white areas in the black background, and return a list of contours in the image:
cnts, h = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
Then for each contours, I use minEnclosingCircle to get the center position of the contour and the radius of the contours.(Why I need the radius? Because most of time, bigger star create larger spike.)
for (i, c) in enumerate(cnts): ((cX, cY), radius) = cv2.minEnclosingCircle(c)
To verify the second step, I draw a red circle on the every contours, which can check I used right position and radius:
cv2.circle(image, (int(cX), int(cY)), int(radius), (0, 0, 255), 3)
Finally, add spikes on these spots.We need to replace red circle to spike image, and resize image based on the size of contour.
I used a PNG file as spike(480 x 480):
overlay = cv2.resize(overlay, (0, 0), fx=scale, fy=scale)
And use opencv addWeighted function to merge two images with transparency:
cv2.addWeighted(overlay, opacity, OriImg, 1, 0, OriImg)
The final image:
Gallery
There are some images processed by this simple script as the reference:
Conclusion
Creating spikes on the dark image maybe the most basic image filter, and you can see these type of filters on the tiktok and other apps. But it can be a good start point if you want to create some special or new filters. At last, all of above code can be download from following github: