I want to use opencv Canny edge detection to crop the image along with the edge. But I have wrote down the edge detection, but still don't know how to
crop the image along with the edge.
import cv2
import numpy as np
image = cv2.imread("test.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # convert image to gray
blur_image = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blur_image, 180, 900)
# cv2.imshow("Image", edged)
# cv2.waitKey(0)
# applying close function
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))
# opened = cv2.morphologyEx(edged, cv2.MORPH_OPEN, kernel)
close = cv2.morphologyEx(edged, cv2.MORPH_CLOSE, kernel)
# cv2.imshow("Closed", close)
# cv2.waitKey(0)
_,contours, hierarchy = cv2.findContours( close.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# work files
# cv2.drawContours(image,contours,-1,(0,0,255),3)
#
# cv2.imshow("result", image)
# mask = np.zeros(image.shape,dtype=np.uint8)
#mask = np.ones((image.height,image.width),dtype=np.uint8)
#m#ask[:,:]= 0
# croped = np.zeros()
cv2.drawContours(image,contours,-1,(0,0,255),3)
cv2.imshow("result", image)
cv2.waitKey(0)
I just want to crop the image along with the red color of the edge.
Related
Hi I am trying to get a mask of a T-shirt.
Here is what I am getting:
However, I would like to only receive the garment's shape without the print in the middle. How can I do that?
Thanks!
Here is the code:
import cv2
import numpy as np
# load image whose you want to create mask
img = cv2.imread('01430_00.jpg')
# convert to graky
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold input image as mask
mask = cv2.threshold(gray,220,220, cv2.THRESH_BINARY)[1]
# negate mask
mask = 255 - mask
# apply morphology to remove isolated extraneous noise
# use borderconstant of black since foreground touches the edges
kernel = np.ones((3,3), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# anti-alias the mask -- blur then stretch
# blur alpha channel
mask = cv2.GaussianBlur(mask, (0,0), sigmaX=2, sigmaY=2, borderType =
cv2.BORDER_DEFAULT)
# linear stretch so that 127.5 goes to 0, but 255 stays 255
mask = (2*(mask.astype(np.float32))-255.0).clip(0,255).astype(np.uint8)
# Show Image in Opencv Windows
cv2.imshow("Original", img)
cv2.imshow("MASK", mask)
# Save mask Image
cv2.imwrite("Mask2.jpg",mask)
cv2.waitKey(0)
cv2.destroyAllWindows()
You already have a large contour for "garment". You can fill inside of the largest contour with the following code
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(contours, key = cv2.contourArea)
cv2.drawContours(mask,[cnt],0,255,-1)
I need to detect only the black rectangle that appears there, but for some reason my code does not detect it but it does detect many other things.
import cv2
img=cv2.imread('vision.png') #read image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Blur=cv2.GaussianBlur(gray,(5,5),1) #apply blur to roi
Canny=cv2.Canny(Blur,10,50) #apply canny to roi
#Find my contours
contours =cv2.findContours(Canny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0]
cntrRect = []
for i in contours:
epsilon = 0.05*cv2.arcLength(i,True)
approx = cv2.approxPolyDP(i,epsilon,True)
if len(approx) == 4:
cv2.drawContours(img,cntrRect,-1,(0,255,0),2)
cv2.imshow('Image Rect ONLY',img)
cntrRect.append(approx)
cv2.waitKey(0)
cv2.destroyAllWindows()
How do I detect only the black rectangle that appears in the image
But this code detect more rectangles and I don't want whis, but I only want detect the black countour rectangle
Here is one way to do that in Python/OpenCV.
Threshold the image. Then use morphology to fill out the rectangle. Then get the largest contour and draw on the input.
Input:
import cv2
import numpy as np
# load image
img = cv2.imread("black_rectangle_outline.png")
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 30, 255, cv2.THRESH_BINARY)[1]
# apply close morphology
kernel = np.ones((111,111), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
# invert so rectangle is white
morph = 255 - morph
# get largest contour and draw on copy of input
result = img.copy()
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
cv2.drawContours(result, [big_contour], 0, (255,255,255), 1)
# write result to disk
cv2.imwrite("black_rectangle_outline_thresh.png", thresh)
cv2.imwrite("black_rectangle_outline_morph.png", morph)
cv2.imwrite("black_rectangle_outline_result.png", result)
# display results
cv2.imshow("THRESH", thresh)
cv2.imshow("MORPH", morph)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold Image:
Morphology Image:
Result:
I try to use python, NumPy, and OpenCV to analyze the image below and just draw a circle on each object found. The idea here is not to identify the bug only identify any object that is different from the background.
Original Image:
Here is the code that I'm using.
import cv2
import numpy as np
img = cv2.imread('per.jpeg', cv2.IMREAD_GRAYSCALE)
if cv2.__version__.startswith('2.'):
detector = cv2.SimpleBlobDetector()
else:
detector = cv2.SimpleBlobDetector_create()
keypoints = detector.detect(img)
print(len(keypoints))
imgKeyPoints = cv2.drawKeypoints(img, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
status = cv2.imwrite('teste.jpeg',imgKeyPoints)
print("Image written to file-system : ",status)
But the problem is that I'm getting only a greyscale image as result without any counting or red circle, as shown below:
Since I'm new to OpenCV and object recognition world I'm not able to identify what is wrong, and any help will be very appreciated.
Here is one way in Python/OpenCV.
Threshold on the bugs color in HSV colorspace. Then use morphology to clean up the threshold. Then get contours. Then find the minimum enclosing circle around each contour. Then bias the radius to make a bit larger and draw the circle around each bug.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('bugs.jpg')
# convert image to hsv colorspace
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# threshold on bugs color
lower=(0,90,10)
upper=(100,250,170)
thresh = cv2.inRange(hsv, lower, upper)
# apply morphology to clean up
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (6,6))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# get external contours
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
result = img.copy()
bias = 10
for cntr in contours:
center, radius = cv2.minEnclosingCircle(cntr)
cx = int(round(center[0]))
cy = int(round(center[1]))
rr = int(round(radius)) + bias
cv2.circle(result, (cx,cy), rr, (0, 0, 255), 2)
# save results
cv2.imwrite('bugs_threshold.jpg', thresh)
cv2.imwrite('bugs_cleaned.jpg', morph)
cv2.imwrite('bugs_circled.jpg', result)
# display results
cv2.imshow('thresh', thresh)
cv2.imshow('morph', morph)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold Image:
Morphology Cleaned Image:
Resulting Circles:
I'm really new to OpenCV. :) I have been working on this for almost an entire day. After hours of sleepless work I would like to know if I can further improve my code.
I have written some code to select only the black markings on the images. These black markings are child contours. Whilst my code is able to select some contours, it isn't accurate. You can see the code draws contours around the shadows along with black markings.
Code 1
At first I tried to use canny edge detection. But I was unable to overlay with the original image correctly.
import cv2
import numpy as np
image = cv2.imread('3.jpg')
image = cv2.resize(image, (500, 500))
image2 = image
cv2.waitKey(0)
# Grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Find Canny edges
edged = cv2.Canny(gray, 30, 200)
cv2.waitKey(0)
contours, hierarchy = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.imshow('Canny', edged)
cv2.waitKey(0)
# print("Number of Contours found = " + str(len(contours)))
cv2.drawContours(image2, contours, -1, (0, 255, 0), 3)
cv2.imshow('Contours', image2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Code 2
I was able to improve on Code 1 to be far more accurate. You should be able to see that it now only selects half of the thumb, none of the other fingers and it doesn't select the indent on the background.
Additionally changing the background of the image also increases the accuracy of the result.
import cv2
import numpy as np
image = cv2.imread('3.jpg', 0)
image2 = cv2.imread('3.jpg')
image = cv2.resize(image, (500, 500))
image2 = cv2.resize(image2, (500, 500))
cv2.waitKey(0)
ret, thresh_basic = cv2.threshold(image, 100, 255, cv2.THRESH_BINARY)
cv2.imshow("Thresh basic", thresh_basic)
# Taking a matrix of size 5 as the kernel
kernel = np.ones((5, 5), np.uint8)
img_erosion = cv2.erode(thresh_basic, kernel, iterations=1)
#####################
ret, thresh_inv = cv2.threshold(img_erosion, 100, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("INV", thresh_inv)
#####################
# Find Canny edges
edged = cv2.Canny(img_erosion, 30, 200)
cv2.waitKey(0)
contours, hierarchy = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.imshow('Canny', edged)
cv2.waitKey(0)
# print("Number of Contours found = " + str(len(contours)))
cv2.imshow('Original', image2)
cv2.drawContours(image2, contours, -1, (0, 255, 0), 3)
cv2.imshow('Contours', image2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Can I improve my code further?
from pdf2image import convert_from_path
import cv2,numpy,os
def pil_to_cv2(image):
open_cv_image = numpy.array(image)
return open_cv_image[:, :, ::-1].copy()
images = convert_from_path('test.pdf')
cv_h=[pil_to_cv2(i) for i in images]
for img in cv_h:
#function_to_crop()
cv2.imwrite('modified.png', img)
How can I remove the extra whiteness from the image (top,sideways,under) without actually intercepting the drawing, The drawings from pdf are from different sizes so I can't crop the images by a fixed number.
Ideally,the output would look like this
Here is another way to do that in Python/OpenCV.
Read the image
Convert to gray and invert the polarity
Threshold
Apply morphology close to fill in holes and make one solid region
Get the outer contour and its bounding box
Use the bounding box to crop the image using Numpy slicing
Save the result
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('multipower.png')
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# invert gray image
gray = 255 - gray
# threshold
thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]
# apply close and open morphology
kernel = np.ones((75,75), np.uint8)
mask = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# get contours (presumably just one around the nonzero pixels)
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
cntr = contours[0]
x,y,w,h = cv2.boundingRect(cntr)
# draw contour on input
contour_img = img.copy()
cv2.drawContours(contour_img,[cntr],0,(0,0,255),3)
# crop to bounding rectangle
crop = img[y:y+h, x:x+w]
# save cropped image
cv2.imwrite('multipower_thresh.png',thresh)
cv2.imwrite('multipower_mask.png',mask)
cv2.imwrite('multipower_contour.png',contour_img)
cv2.imwrite('multipower_cropped.png',crop)
# show the images
cv2.imshow("THRESH", thresh)
cv2.imshow("MASK", mask)
cv2.imshow("CONTOUR", contour_img)
cv2.imshow("CROP", crop)
cv2.waitKey(0)
cv2.destroyAllWindows()
Thresholded Image:
Morphology closed image:
Contour image:
Result:
import cv2 as cv
import numpy as np
frame = cv.imread('7dcoI.png')
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
mask=cv.threshold(frame_gray, 85, 255, cv.THRESH_BINARY )[1]
rows, cols = mask.shape
non_empty_columns = np.where(mask.min(axis=0)==0)[0]
non_empty_rows = np.where(mask.min(axis=1)==0)[0]
cropBox = (min(non_empty_rows), min(max(non_empty_rows), rows), min(non_empty_columns), min(max(non_empty_columns), cols))
cropped = frame[cropBox[0]:cropBox[1]+1, cropBox[2]:cropBox[3]+1 , :]
cv.imwrite('out_mask.png', cropped)