I tried to detect the external circle of that image
However, no matter how I set the params of the Hough Transform, I can't detect the external circle.
My code is the next:
###############################
#Circle detection
###############################
height, width = image.shape
circles = cv2.HoughCircles(image,cv2.HOUGH_GRADIENT,.3,20,param1=100,param2=100,minRadius=int(min(width,height)/3),maxRadius=int(min(width,height)))
circles = np.uint16(np.around(circles))
cimg=origin
for i in circles[0,:]:
cv2.circle(cimg,(i[0],i[1]),i[2],(255,0,0),1) #DRAW ALL CIRCLES IN BLUE
cv2.circle(cimg,(i[0],i[1]),2,(255,0,0),1)
###############################
#FIND HIGHER CIRCLE
###############################
#I go through all the circles and
#take the one with the greatest radio
max_index=0
max_i=circles[0,max_index,2]
for indx, i in enumerate(circles[0,:]):
if i[2]>max_i:
max_i=i[2]
max_index=indx #indx of higher circle
circle_max=max_i
x_max=circles[0,max_index,0]
y_max=circles[0,max_index,1]
r_max=circles[0,max_index,2]
cv2.circle(cimg,(x_max,y_max),r_max,(0,0,255),1) #DRAW HIGHER CIRCLE IN RED
cv2.circle(cimg,(x_max,y_max),2,(0,0,255),3)
This code detect a lot of circles, but the external circle never appears.
If you want to detect only one circle, this can help you:
import cv2
import numpy as np
from matplotlib import pyplot as plt
name_image = "ImageTest.png"
bgr_img = cv2.imread(name_image)
b,g,r = cv2.split(bgr_img) # get b,g,r
rgb_img = cv2.merge([r,g,b]) # switch it to rgb
gray_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(gray_img, 5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,7,20,
param1=90,param2=2400,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
plt.subplot(121),plt.imshow(rgb_img)
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(cimg)
plt.title('Hough Transform'), plt.xticks([]), plt.yticks([])
plt.show()
cv2.imwrite(name_image.split(".png")[0] +'_HoughTransform.png', cimg)
Related
I want to create a color gradient without the need to blur out the entire resulting image. Basically I want to create a gradient along the line where the colors meet. I have seen codes doing linear or radial gradients, but I don't know which one would work best or if there is another way to create the gradients.
import cv2 as cv
import matplotlib.pyplot as plt
## load the image in RGB color space
original_image = cv.imread("BEACH.jpeg")
## convert our image from RGB Colours Space to HSV
img = cv.cvtColor(original_image, cv.COLOR_BGR2RGB)
## convert our image to a matrix
vectorized = img.reshape((-1, 3))
## We convert the unit8 values to float as it is a requirement of the k-means method of OpenCV.
vectorized = np.float32(vectorized)
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 2
attempts = 100
ret, label, center = cv.kmeans(vectorized, K, None, criteria, attempts, cv.KMEANS_PP_CENTERS)
center = np.uint8(center)
res = center[label.flatten()]
result_image = res.reshape(img.shape)
figure_size = 5
plt.figure(figsize=(figure_size, figure_size))
plt.subplot(1, 2, 1), plt.imshow(img)
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(result_image)
plt.title('Segmented Image when K = %i' % K), plt.xticks([]), plt.yticks([])
plt.show()
I want to skeletonize an image with the function skeletonize from skimage.morphology but the result is really disappointing. Meaning it fails to recognize the horizontal and vertical lines connecting the different instruments of the drawing.
Any tips? What can I improve?
import cv2 as cv
from matplotlib import pyplot as plt
from skimage import filters
from skimage.morphology import skeletonize
# read image
img = cv.imread('realpars_p_id_diag_mod.png',0)
binary = img > filters.threshold_triangle(img)
# true false to one
binary_cp = binary.copy()
binary_cp[binary_cp == True] = 1
binary_cp[binary_cp == False] = 0
# skeletonize image
skeleton = skeletonize(binary_cp)
# print images
plt.figure(figsize=(20,20))
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(skeleton,cmap = 'gray')
plt.title('skeleton Image'), plt.xticks([]), plt.yticks([])
plt.savefig("binary and bin_skeleton.png")
plt.show()
That is disappointing! 😂 But there's clues in the curvature of the lines, and the fact that the diagonals go in the opposite direction as they do in the original image: you are skeletonizing the wrong image! You want to skeletonize the black parts, not the white parts, which means you need to invert the binary image. Or, more simply, change the sign in the threshold expression. Here's my updated code:
from skimage import io
from matplotlib import pyplot as plt
from skimage import filters
from skimage.morphology import skeletonize
# read image
img = io.imread('/Users/jni/Downloads/P4tB1.jpg')[..., 0]
# Note: we want the black bits to be True, so use <
binary = img < filters.threshold_triangle(img)
# skeletonize image
skeleton = skeletonize(binary)
# print images
fig, ax = plt.subplots(1, 2)
ax[0].imshow(img, cmap='gray')
ax[0].set_title('original')
ax[0].set_axis_off()
# note the reversed colormap, gray_r
ax[1].imshow(skeleton, cmap='gray_r')
ax[1].set_title('skeleton (inverse)')
ax[1].set_axis_off()
plt.show()
Result:
The unfiltered imageI have a 2D image of a vessel in grayscale and I want to convert it to a 3D model for further analysis.
I’ve imported it using opencv (cv2) library and I’ve written a code for detecting the edges of the shape in the image.
But, I have some problem with detecting the center-line by using the edges coordinates.I want the center-line for revolving the shape and convert it to a 3D model)
I appreciate any help.
Here is the image but as you can see the line hasn't been fitted to the middle of the shape.
import cv2
import numpy as np
from matplotlib import pyplot as plt
#Applying the bilateral blur to the image
img = cv2.imread('vessel.png')
blur = cv2.bilateralFilter(img,9,75,75)
#Applying the Canny edge detection to the blurred image to find the edges
edges = cv2.Canny(blur,100,200)
#Getting the coordinateof the pixels
x , y = np.where(edges > 0.5)
#Getting the regression line (slope and intercept)
m, b = np.polyfit(x, y, deg=1)
#Drowing the line in the image
edges_img = cv2.line(edges, (int(0 * m + b), 0), (int(500*m+b), 500) , color = (255,0,0) ,
thickness = 2)
#plotting the result in comparison with the raw image
plt.subplot(121),plt.imshow(blur,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges_img,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()`
I'm using the cv2.HoughCircles in Python trying to detect circles in the following image.the image
here is my code:
import matplotlib.pyplot as plt
import cv2
import numpy as np
image = cv2.imread("image.png")
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.5, 10, param1=20, param2=60, minRadius=0, maxRadius=40)
print(circles)
if circles is not None:
circles = np.round(circles[0, :]).astype("int")
for (x, y, r) in circles:
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(output, (x - 3, y - 3), (x + 3, y + 3), (0, 128, 255), -1)
plt.subplot(121), plt.imshow(image, cmap="gray"), plt.title("corners")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(output, cmap="gray"), plt.title("corners")
plt.xticks([]), plt.yticks([])
plt.show()
the detected circles
any insight on why it isn't detecting the circles?
attaching an image of the circles i would like to detect. i would like to detect as many circles like the ones in red in the following image.example of circles i would like to detect
I am trying to extract the edge of an image (its contour) and change its thickness. I want to give it like the stroke effect of Photoshop layer style. Photoshop stroke effect example:
http://projectwoman.com/2012/11/smart-objects-and-strokes-in-photoshop.html
I was able to extract the edge from an image. Using canny edge or the pillow function.
1.using canny edge detection
img = cv2.imread(img_path,0)
edges = cv2.Canny(img,300,700)
2.using pillow filler
image = Image.open(img_path).convert('RGB')
image = image.filter(ImageFilter.FIND_EDGES())
but, I could not adjust the contour thickness.
Here a solution:
import cv2
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
image = cv2.imread('mickey.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2YCR_CB)[...,0]
def show_img(im, figsize=None, ax=None, alpha=None):
if not ax: fig,ax = plt.subplots(figsize=figsize)
ax.imshow(im, alpha=alpha)
ax.set_axis_off()
return ax
def getBordered(image, width):
bg = np.zeros(image.shape)
_, contours, _ = cv2.findContours(image.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
biggest = 0
bigcontour = None
for contour in contours:
area = cv2.contourArea(contour)
if area > biggest:
biggest = area
bigcontour = contour
return cv2.drawContours(bg, [bigcontour], 0, (255, 255, 255), width).astype(bool)
im2 = getBordered(image, 10)
show_img(im2, figsize=(10,10))
You can change thickness by changing param width in getBordered.