Detecting rectangle in image - image

I would like to ask if somebody could help me with rectangle detection in image.
I've tried contour detection, but results are not sufficient.
I'd be thankful for any ideas.
I have tried this:
EDIT 1
# loading image
im = cv2.imread('b.jpeg',cv2.IMREAD_GRAYSCALE)
# equalization
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
im = clahe.apply(im)
# bluring image
im = cv2.GaussianBlur(im,(5,5),0)
# edge detection
edges = cv2.Canny(im,100,200)
cv2.imshow('Canny',edges)
cv2.moveWindow('Canny',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()
# contour extraction
ret,thresh = cv2.threshold(edges,50,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(im, contours, -1, (0,255,0), 3)
cv2.imshow('Contour',im)
cv2.moveWindow('Contour',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()
cntrRect = []
for i in contours:
approx = cv2.approxPolyDP(i,0.1*cv2.arcLength(i,True),True)
x,y,w,h = cv2.boundingRect(approx)
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
#peri = cv2.arcLength(i,True)
epsilon = 0.1*cv2.arcLength(i,True)
#0.02*peri
approx = cv2.approxPolyDP(i,epsilon,True)
if len(approx) == 4:
cntrRect.append(approx)
cv2.imshow('Contour2',im)
cv2.moveWindow('Contour2',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.drawContours(im, cntrRect, -1, (255,0,0), 3)
cv2.imshow('Contour3',im)
cv2.moveWindow('Contour3',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()

Related

How can I make the `cv2.imshow` output the same as the `plt.imshow` output?

How can I make the cv2.imshow output the same as the plt.imshow output?
# loading image
img0 = cv2.imread("image.png")
# converting to gray scale
gray = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)
# remove noise
img = cv2.GaussianBlur(gray, (3, 3), 0)
# convolute with proper kernels
laplacian = cv2.Laplacian(img, cv2.CV_64F)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5) # x
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5) # y
imgboth = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
plt.imshow(imgboth, cmap='gray')
plt.show()
cv2.imshow("img", cv2.resize(imgboth, (960, 540)))
cv2.waitKey(0)
cv2.destroyAllWindows()
original image
plt.output
cv2.imshow
# ...
canvas = imgboth.astype(np.float32)
canvas /= np.abs(imgboth).max()
canvas += 0.5
cv.namedWindow("canvas", cv.WINDOW_NORMAL)
cv.imshow("canvas", canvas)
cv.waitKey()
cv.destroyWindow("canvas")
only looks different because you posted thumbnails, not the original size image.
when you give imshow floating point values, which you do because laplacian and sobelx are floating point, then it assumes a range of 0.0 .. 1.0 as black .. white.
matplotlib automatically scales data. OpenCV's imshow doesn't. both behaviors have pros and cons.

TypeError: Expected Ptr<cv::UMat> for argument 'array'

The following is the code I have written: I am getting the following error while executing this code-
**
x,y,w,h = cv2.boundingRect(contours) TypeError: Expected Ptr<cv::UMat>
for argument 'array'
I am trying to make the rectangle outside my contours
**
from cv2 import cv2
import numpy as np
cam = cv2.VideoCapture(0)
kernel_open = np.ones((7,7), np.uint8)
kernel_close = np.ones((15,15), np.uint8)
while True:
ret, frame = cam.read()
frame = cv2.resize(frame, (340,220))
# Our image is in BGR format. We need to conver it into HSV
imgHSV = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Now we'll apply masking to capture green colour
lower_lim = np.array([33, 80, 40])
upper_lim = np.array([102, 255, 255])
mask = cv2.inRange(imgHSV, lower_lim, upper_lim)
# As we are getting noises so we'll remove the noise by morphological transformation- Opening and Closing
mask_open = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel_open)
mask_close = cv2.morphologyEx(mask_open, cv2.MORPH_CLOSE, kernel_close)
# Till now we have identified the colour of the image we want
# Now we'll make boundary or contours around our required colour image
contours, hierarchy = cv2.findContours(mask_close.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(frame, contours, -1, (0,0,255), 3)
# Now we'll draw rectangles
for i in range(len(contours)):
x,y,w,h = cv2.boundingRect(contours)
cv2.rectangle(frame, (x,y), (x+w, y+h), (255,0,0), 3)
cv2.imshow('Original Image', frame)
cv2.imshow('Mask Closed Image', mask_close)
if cv2.waitKey(1) == 27:
break
cam.release()
cv2.destroyAllWindows()
Cast your mask_close array as an unsigned 8-bit integer array
cv2.findContours((mask_close.astype(np.uint8).copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
you can try
we need to make it mask_close= mask_close[0]
replace your code
contours, hierarchy = cv2.findContours(mask_close.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
with
mask_close= mask_close[0] contours, hierarchy = cv2.findContours(mask_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
Replace the line:
contours, hierarchy = cv2.findContours(mask_close.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
with the following lines:
contours, hierarchy = cv2.findContours(mask_close.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2:]
Actually, in a particular version of OpenCV, cv2.findContours() function returns 3 values instead of 2. The three values being: image, contours, hierarchy in the same order.
I think you are using that version only that is why this is happening.

How can i find center coordinates of a group object opencv

I want to center x,y coordinates of all delight lokums in this picture;
marshmallows on a tray
i tried a lot of things but i cant complete rectangles.
i get this image
enter image description here
target my project
project target
import cv2
import numpy as np
img = cv2.imread ('yl4.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#morphology
kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(gray,kernel,iterations = 1)
kernel = np.ones((17,17),np.uint8)
opening = cv2.morphologyEx(gray , cv2.MORPH_OPEN, kernel)
#get binary
gray_blur = cv2.GaussianBlur(opening, (21,21), 0)
thresh = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV, 11, 1)
kernel = np.ones((3,3),np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = np.ones((7,7),np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
#filter small dotted regions
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh , None, None, None, 4, cv2.CV_32S)
sizes = stats[1:, -1] #get CC_STAT_AREA component
img2 = np.zeros((labels.shape), np.uint8)
for i in range(0, nlabels - 1):
if sizes[i] >= 275:
img2[labels == i + 1] = 255
cv2.imshow('frame',img2)
cv2.imshow('gray',gray)
cv2.imwrite("outyl3.jpg", img2)
cv2.waitKey(0)

How to color the mask image obtained out of a polygon

I am getting a mask out of a polygon and below is the image. Now I see that there is a white boundary but I want not just the boundary but inside boundary as white too.
Here is my code:
sar_polygon = Image.new('L', (int(range_samples), int(azimuth_lines)), 0)
draw = ImageDraw.Draw(sar_polygon)
for vertex in range(len(sar_ver)):
st = sar_ver[vertex]
try:
end = sar_ver[vertex + 1]
except IndexError:
end = sar_ver[0]
draw.line((st[0], st[1], end[0], end[1]), fill=1)
sar_polygon.save('polygon.jpg', 'JPEG')
You are currently drawing lines along the edges. You are interested in the polygon method, or perhaps the rectangle method - http://pillow.readthedocs.io/en/5.2.x/reference/ImageDraw.html#PIL.ImageDraw.PIL.ImageDraw.ImageDraw.polygon.
from PIL import Image, ImageDraw
sar_polygon = Image.new('RGB', (500, 500))
draw = ImageDraw.Draw(sar_polygon)
sar_ver = ((100,100),(200,100),(200,200),(100,200))
draw.polygon(sar_ver, fill='#f00')
sar_polygon.save('polygon.jpg', 'JPEG')

ROI is written in lighter colors than original picture

I'm trying to locate an object (here a PWB) on a picture.
First I do this by finding the largest contour. Then I want to rewrite solely this object into a new picture so that in the future I can work on smaller pictures.
The problem however is that when I rewrite this ROI, the picture gets of a lighter color than the original one.
CODE:
Original = cv2.imread(picture_location)
image = cv2.imread(mask_location)
img = cv2.medianBlur(image,29)
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = cv2.bitwise_and(Original, image)
roi = cv2.add(dst, Original)
ret,thresh = cv2.threshold(imgray,127,255,0)
im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
area = 0
max_x = 0
max_y = 0
min_x = Original.shape[1]
min_y = Original.shape[0]
for i in contours:
new_area = cv2.contourArea(i)
if new_area > area:
area = new_area
cnt = i
x,y,w,h = cv2.boundingRect(cnt)
min_x = min(x, min_x)
min_y = min(y, min_y)
max_x = max(x+w, max_x)
max_y = max(y+h, max_y)
roi = roi[min_y-10:max_y+10, min_x-10:max_x+10]
Original = cv2.rectangle(Original,(x-10,y-10),(x+w+10,y+h+10),(0,255,0),2)
#Writing down the images
cv2.imwrite('Pictures/PCB1/LocatedPCB.jpg', roi)
cv2.imwrite('Pictures/PCB1/LocatedPCBContour.jpg',Original)
Since I don't have 10 reputation yet I cannot post the pictures. I can however provide the links:
Original
Region of Interest
The main question is how do I get the software to write down the ROI in the exact same colour as the original picture?
I'm a elektromechanical engineer however, so I'm fairly new to this, remarks on the way I wrote my code would also be appreciated if possible.
The problem is that you first let roi = cv2.add(dst, Original)
and finally cut from the lighten picture in here:
roi = roi[min_y-10:max_y+10, min_x-10:max_x+10]
If you want to crop the original image, you should do:
roi = Original[min_y-10:max_y+10, min_x-10:max_x+10]
You can perhaps perform an edge detection after blurring your image.
How to select best parameters for Canny edge? SEE HERE
lower = 46
upper = 93
edged = cv2.Canny(img, lower, upper) #--- Perform canny edge on the blurred image
kernel = np.ones((5,5),np.uint8)
dilate = cv2.morphologyEx(edged, cv2.MORPH_DILATE, kernel, 3) #---Morphological dilation
_, contours , _= cv2.findContours(dilate, cv2.RETR_EXTERNAL, 1) #---Finds all parent contours, does not find child contours(i.e; does not consider contours within another contour)
max = 0
cc = 0
for i in range(len(contours)): #---For loop for finding contour with maximum area
if (cv2.contourArea(contours[i]) > max):
max = cv2.contourArea(contours[i])
cc = i
cv2.drawContours(img, contours[cc], -1, (0,255,0), 2) #---Draw contour having the maximum area
cv2.imshow(Contour of PCB.',img)
x,y,w,h = cv2.boundingRect(cnt[cc]) #---Calibrates a straight rectangle for the contour of max. area
crop_img = img1[y:y+h, x:x+w] #--- Cropping the ROI having the coordinates of the bounding rectangle
cv2.imshow('cropped PCB.jpg',crop_img)

Resources