Reputation: 53
i am using python with opencv and numpy, to detect stars in astronomical for example this one1 images. Using template matching I have got it to detect stars with a threshold (click the 2) 2 by drawing a rectangle around a star template. My next goal is to essentially "remove" the stars from the image.
To do this, I have tried blurring the image with different methods, cv2.blur etc, but it doesn't create the effect i am looking for. My next idea was to get rgb data from pixels around the star, average them out, and color in the star with the selected colour. Is this the best option and how would i do this?
my code is as below.
import cv2
import numpy as np
import time
start = time.time()
threshold = 0.4
image = cv2.imread('lag.jpg')
imageG = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#cv2.imshow('original', image)
#cv2.imshow('greyscale', imageG)
template = cv2.imread('template.jpg', 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(imageG,template,cv2.TM_CCOEFF_NORMED)
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
a = cv2.rectangle(image, pt, (pt[0] + w, pt[1] + h), (0,0,255), 1)
cv2.imshow('lag.jpg', image)
end = time.time()
final = end - start
print(final)
cv2.waitKey(0)
cv2.destroyAllWindows()
Upvotes: 4
Views: 8458
Reputation: 32084
You may create a mask, and use cv2.inpaint for replacing the selected "mask area" using the pixel near the area boundary.
Since you didn't post 'template.jpg'
, I created the following one:
Building a mask by drawing filled rectangles on zeros image:
mask = np.zeros_like(imageG)
for pt in zip(*loc[::-1]):
#a = cv2.rectangle(image, pt, (pt[0] + w, pt[1] + h), (0,0,255), 1)
cv2.rectangle(mask, (pt[0]+3, pt[1]+3), (pt[0]+w-3, pt[1]+h-3), 255, -1) # Reduce the size of the rectangle by 3 pixels from each side.
Note: I used cv2.rectangle
for keeping your original code, but I think circles may by better in your case.
Using inpaint
for removing the masked area:
image = cv2.inpaint(image, mask, 2, cv2.INPAINT_NS)
You may tune the parameters.
Here is the complete code:
import cv2
import numpy as np
import time
start = time.time()
threshold = 0.4
image = cv2.imread('lag.jpg')
imageG = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#template = cv2.imread('template.jpg', 0)
template = cv2.imread('template.png', 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(imageG,template,cv2.TM_CCOEFF_NORMED)
loc = np.where( res >= threshold)
mask = np.zeros_like(imageG)
for pt in zip(*loc[::-1]):
#a = cv2.rectangle(image, pt, (pt[0] + w, pt[1] + h), (0,0,255), 1)
cv2.rectangle(mask, (pt[0]+3, pt[1]+3), (pt[0]+w-3, pt[1]+h-3), 255, -1) # Reduce the size of the rectangle by 3 pixels from each side
image = cv2.inpaint(image, mask, 2, cv2.INPAINT_NS)
cv2.imshow('lag.jpg', image)
cv2.imshow('mask', mask)
end = time.time()
final = end - start
print(final)
cv2.waitKey(0)
cv2.destroyAllWindows()
Results:
Original image (for comparison):
You may improve the solution using few sizes of rectangles (or circles) - use larger rectangles for covering the larger stars.
Upvotes: 6