I am trying to find centroid of circular shape with the help of OpenCV Sift for my project.
After finding centroid try to fit a encoding ring to detect type of marker. The SIFT algorithm is the best for my project, since it is scalar and rotation invariant. It seems to detect the keypoint of centroid of object and i am trying to get the coordinates of it.
import cv2
import numpy as np
def findSift(img, gray, draw=True):
sift = cv2.SIFT_create(10)
kp = sift.detect(gray, None)
if draw:
cv2.drawKeypoints(img, kp, img)
kp_coordinates = cv2.KeyPoint_convert(kp)
return kp_coordinates
if __name__ == "__main__":
img = cv2.imread('Test.jpg')
print(img.shape[:2])
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Array_Cooridinates = findSift(img,gray)
cv2.imshow('img',img)
cv2.waitKey(0)
Image Resolution: (849, 734)
Array of coordinates of keypoints detected:
[[346.20126 385.5532 ]
[366.1102 217.0911 ]
[366.1102 217.0911 ]
[482.2291 451.484 ]
[482.2291 451.484 ]
[468.70483 303.86118]
[468.70483 303.86118]
[385.93945 296.0943 ]
[417.37436 445.36234]
[441.80768 377.35934]]
If someone have any reference to my problem, feel free to post it so i can do more research about it.
Thanks for any help here!
Have a nice day.
Related
In detectron2 the output get the bellow output upon predection.
panoptic_seg, segments_info = predictor(im)["panoptic_seg"]
it can be drawn via draw_panoptic_seg_predictionsfunction, but we want to save the mask deatils & redraw using opencv how can we do that ?
for instance segmentation we can do like this :
import cv2
import numpy as np
# "outputs" is the inference output in the format described here - https://detectron2.readthedocs.io/tutorials/models.html#model-output-format
# Extract the contour of each predicted mask and save it in a list
contours = []
for pred_mask in outputs['instances'].pred_masks:
# pred_mask is of type torch.Tensor, and the values are boolean (True, False)
# Convert it to a 8-bit numpy array, which can then be used to find contours
mask = pred_mask.to("cpu").numpy().astype('uint8')
contour, _ = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
contours.append(contour[0]) # contour is a tuple (OpenCV 4.5.2), so take the first element which is the array of contour points
and then draw the mask with this code
# "image" is the original BGR image
image_with_overlaid_predictions = im.copy()
for contour in contours:
cv2.drawContours(image_with_overlaid_predictions, [contour], -1, (0,255,0), 20)
plt.figure()
plt.imshow(image_with_overlaid_predictions)
I want to achive similar with pantopic mask
Greeting,
I have been trying to extract some regions from the face
In this case (upper lip) using Dlib, the thing is after extracting the ROI (which look perfect) I realized that there is some noise around the ROI
Can't figure out what I'm doing wrong, and how to resolve this issue.
This is the used Python code:
import cv2
import numpy as np
import dlib
import os
from scipy import ndimage, misc
import time
def extract_index_nparray(nparray):
index = None
for num in nparray[0]:
index = num
break
return index
img = cv2.imread( 'input_facial_image.jpg')
img=cv2.resize(img,(512,512))
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
mask = np.zeros_like(img_gray)
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("/facial-landmarks-recognition/shape_predictor_68_face_landmarks.dat")
# Face 1
faces = detector(img_gray)
for face in faces:
landmarks = predictor(img_gray, face)
landmarks_points = []
for n in [48,49,50,51,52,53,54,64,63,62,61,60]:
x = landmarks.part(n).x
y = landmarks.part(n).y
landmarks_points.append((x, y))
points = np.array(landmarks_points, np.int32)
convexhull = cv2.convexHull(points)
# cv2.polylines(img, [convexhull], True, (255, 0, 0), 3)
cv2.fillConvexPoly(mask, convexhull, 255)
face_image_1 = cv2.bitwise_or(img, img, mask=mask)
cv2.imwrite('extracted_lips.jpg', face_image_1 )
The extracted image looks like this :
upper lips extracted image
But in further steps in my work, I realized a noise around the upper lip, so I examined and I found unclean_upperlip
Is there any way to get rid of the noise during the ROI extracting or any image processing technique to bypass this issue?
Thanks in advance
For anyone who faced the same issue as me, it's simple. Just change the output format to png. The JPG compressing is the issue here.
I hope that this helps
I have been working on a code where an image is given as shown
I have to place this knife onto some other image. The condition is that I have to crop the knife along its outline and not in a rectangular box.
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('2.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
img_blur = cv2.bilateralFilter(img, d = 7,
sigmaSpace = 75, sigmaColor =75)
img_gray = cv2.cvtColor(img_blur, cv2.COLOR_RGB2GRAY)
a = img_gray.max()
_, thresh = cv2.threshold(img_gray, a/2+60, a,cv2.THRESH_BINARY_INV)
plt.imshow(thresh, cmap = 'gray')
contours, hierarchy = cv2.findContours(
image = thresh,
mode = cv2.RETR_TREE,
method = cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key = cv2.contourArea, reverse = True)
img_copy = img.copy()
final = cv2.drawContours(img_copy, contours, contourIdx = -1,
color = (255, 0, 0), thickness = 2)
plt.imshow(img_copy)
This is what I have tried but it doesn't seem to work well.
Input
Output
You can do it starting with bounding box using snake algorithm with balloon force added.
Snake's algo is defined such that it minimizes 3 energies - Continuity, Curvature and Gradient. The first two (together called internal energy) get minimized when points (on curve) are pulled closer and closer i.e. contract. If they expand then energy increases which is not allowed by snake algorithm.
But this initial algo proposed in 1987 has a few problems. One of the problem is that in flat areas (where gradient is zero) algo fails to converge and does nothing. There are several modifications proposed to solve this problem. The solution of interest here is - Balloon Force proposed by LD Cohen in 1989.
Balloon force guides the contour in non-informative areas of the image, i.e., areas where the gradient of the image is too small to push the contour towards a border. A negative value will shrink the contour, while a positive value will expand the contour in these areas. Setting this to zero will disable the balloon force.
Another improvement is - Morphological Snakes which use morphological operators (such as dilation or erosion) over a binary array instead of solving PDEs over a floating point array, which is the standard approach for active contours. This makes Morphological Snakes faster and numerically more stable than their traditional counterpart.
Scikit-image's implementation using the above two improvements is morphological_geodesic_active_contour. It has a parameter balloon
Using your image
import numpy as np
import matplotlib.pyplot as plt
from skimage.segmentation import morphological_geodesic_active_contour, inverse_gaussian_gradient
from skimage.color import rgb2gray
from skimage.util import img_as_float
from PIL import Image, ImageDraw
im = Image.open('knife.jpg')
im = np.array(im)
im = rgb2gray(im)
im = img_as_float(im)
plt.imshow(im, cmap='gray')
Now let us create a function which will help us to store iterations:
def store_evolution_in(lst):
"""Returns a callback function to store the evolution of the level sets in
the given list.
"""
def _store(x):
lst.append(np.copy(x))
return _store
This method needs image to be preprocessed to highlight the contours. This can be done using the function inverse_gaussian_gradient, although the user might want to define their own version. The quality of the MorphGAC segmentation depends greatly on this preprocessing step.
gimage = inverse_gaussian_gradient(im)
Below we define our starting point - a bounding box.
init_ls = np.zeros(im.shape, dtype=np.int8)
init_ls[200:-400, 20:-30] = 1
List with intermediate results for plotting the evolution
evolution = []
callback = store_evolution_in(evolution)
Now required magic line for morphological_geodesic_active_contour with balloon contraction is below:
ls = morphological_geodesic_active_contour(gimage, 200, init_ls,
smoothing=1, balloon=-0.75,
threshold=0.7,
iter_callback=callback)
Now let us plot the results:
fig, axes = plt.subplots(1, 2, figsize=(8, 8))
ax = axes.flatten()
ax[0].imshow(im, cmap="gray")
ax[0].set_axis_off()
ax[0].contour(ls, [0.5], colors='b')
ax[0].set_title("Morphological GAC segmentation", fontsize=12)
ax[1].imshow(ls, cmap="gray")
ax[1].set_axis_off()
contour = ax[1].contour(evolution[0], [0.5], colors='r')
contour.collections[0].set_label("Starting Contour")
contour = ax[1].contour(evolution[25], [0.5], colors='g')
contour.collections[0].set_label("Iteration 25")
contour = ax[1].contour(evolution[-1], [0.5], colors='b')
contour.collections[0].set_label("Last Iteration")
ax[1].legend(loc="upper right")
title = "Morphological GAC Curve evolution"
ax[1].set_title(title, fontsize=12)
plt.show()
With more balloon force you can get only the blade of knife as well.
ls = morphological_geodesic_active_contour(gimage, 100, init_ls,
smoothing=1, balloon=-1,
threshold=0.7,
iter_callback=callback)
Play with these parameters - smoothing, balloon, threshold to get your perfect curve
I am doing GoPro camera calibration with OpenCv. But findChessboardCorners return false on many of my images and Matlab not. I have tried to biniraze images to help OpenCv but it helps only in some cases. Here is example:
Here is code:
CHECKERBOARD = (6,9)
img = cv2.imread('1.JPG')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
print(ret)
I have tried different flags. OpenCv fails and matlab not. Any hint?
Resizing the image seems to work.
Code Sample:
import cv2
import numpy as np
CHECKERBOARD = (6,9)
img = cv2.imread("Q2l11.jpg")
img = cv2.resize(img,(int(400),int(400)))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
print(corners)
#print(ret)
corners = np.int0(corners)
for i in corners:
x,y = i.ravel()
cv2.circle(img,(x,y),3,(0,0,255),-1)
cv2.imshow('Corners',img)
cv2.waitKey(0)
Result:
I am trying to detect the eyes' irises but HoughCircles returns 0 circles.
The input image(eyes) is:
Then I made the following things with this image:
cvtColor(eyes, gray, CV_BGR2GRAY);
morphologyEx(gray, gray, 4,cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3)));
threshold(gray, gray, 0, 255, THRESH_OTSU);
vector<Vec3f> circles;
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray.rows/4);
if (circles.size())
cout << "found" << endl;
So the final gray image looks like this:
I've found this question Using HoughCircles to detect and measure pupil and iris but it didn't help me despite the similarity with my issue.
So why does HoughCircles return 0 circles while trying to detect irises?
If someone knows any better way to find irises, you are welcome.
I have faced the exact same issue for the same problem. Turns out houghcircles is not a very good method for detecting not-so-well-formed circles.
Feature detection methods like MSER work better in these cases.
import cv2
import math
import numpy as np
import sys
def non_maximal_supression(x):
for f in features:
distx = f.pt[0] - x.pt[0]
disty = f.pt[1] - x.pt[1]
dist = math.sqrt(distx*distx + disty*disty)
if (f.size > x.size) and (dist<f.size/2):
return True
thresh = 70
img = cv2.imread(sys.argv[1])
bw = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
detector = cv2.FeatureDetector_create('MSER')
features = detector.detect(bw)
features.sort(key = lambda x: -x.size)
features = [ x for x in features if x.size > 70]
reduced_features = [x for x in features if not non_maximal_supression(x)]
for rf in reduced_features:
cv2.circle(img, (int(rf.pt[0]), int(rf.pt[1])), int(rf.size/2), (0,0,255), 3)
cv2.imshow("iris detection", img)
cv2.waitKey()
Alternatively you can try convolutional filters.
EDIT:
For the ones who have issues with c++ MSER, here is a basic gist.