'How can i find selected area in photo using OpenCV?
I need to detect a selected area in a photo:
Original photo:
I used this code:
import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('./Pictures/GreenPool720.png',))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=1, maxLineGap=30)
for line in lines:
x1,y1,x2,y2 = line[0]
cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv.imshow('1', img)
cv.waitKey()
And got this photo:
Please tell me what to do so that I get the right photo
Solution 1:[1]
Basic Idea
The green color is pretty distinct in the image and can be segmented using a different color space. Here we use the LAB color space to segment the green from the a-component. The a-component represents color variation between red and green making easy to isolate either color. More on this here
Once the green board is segmented you can follow your approach.
Approach:
- Segmenting green pool board:
- Perform Otsu Threshold on a-component
- Find the largest contour and create a mask out of it
- Capture the region of interest (green board)
- Edge detection using Canny algorithm
- Line detection using Hough transform
- Post processing to filter out unwanted lines
Code:
img = cv2.imread('image_path')
# creating a duplicate copy
img2 = img.copy()
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_comp = lab[:,:,1]
# Otsu Threshold on a-channel
th = cv2.threshold(a_comp,127,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
# Finding the contour with maximum area and create a mask
contours, hierarchy = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)
black = np.zeros((img.shape[0], img.shape[1]), np.uint8)
mask = cv2.drawContours(black,[c],0,255, -1)
# Mask out the green board
anded = cv2.bitwise_and(img, img, mask = mask)
# Following the approach as above
gray = cv2.cvtColor(anded,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength=1, maxLineGap=30)
for line in lines:
x1,y1,x2,y2 = line[0]
cv2.line(img2,(x1,y1),(x2,y2),(0,255,0),2)
# to avoid the lines detected on the edge of the board, perform erosion on the mask
kernel_ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
erode = cv2.erode(mask, kernel_ellipse, iterations=1)
fin = cv2.bitwise_and(img2, img2, mask = erode)
fin2 = fin.copy()
fin2[erode[:] == 0,...] = img[erode[:] == 0,...]
In the above, assign pixel values from the original image where the mask (erode) has black pixels:
You can tweak the parameters of cv2.HoughLinesP() to get better results
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |








