Selecting contours inside a contour (OpenCV, Python) - python

I am trying to select circles inside a square from a photo. I managed to select the square but I am having troubles with selecting the circles. I think the main problem is my threshold but I don't know how to configure it correctly.
[my image]
(https://i.stack.imgur.com/zwVFQ.jpg)
There is my code:
import cv2
import numpy as np
image = cv2.imread('photo/5.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 0, 255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
opening = cv2.morphologyEx(close, cv2.MORPH_OPEN, kernel, iterations=2)
height= image.shape[0]
width = image.shape[1]
size = height*width
cnts, hierarchy = cv2.findContours(opening, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
trees = 0
trees_area= 0
hierarchy = hierarchy[0]
for component in zip(cnts, hierarchy):
currentContour = component[0]
currentHierarchy = component[1]
x,y,w,h = cv2.boundingRect(currentContour)
if currentHierarchy[1] < 0:
cv2.rectangle(image,(x,y),(x+w,y+h),(0,0,255),3)
elif currentHierarchy[2] < 0:
cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),3)
print('Trees:', trees)
print('Area:', trees_area)
print('Size:', size)
print('Fibre_area', "{:.2f}".format((trees_area/size)*100))
cv2.imshow('image', image)
cv2.waitKey()

Related

My Opencv/Pytesseract script can't detect characters

I have this code:
img = cv2.imread("image.jpg", cv2.IMREAD_UNCHANGED)
img = imutils.resize(img, width=500)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite("output/grayscale conversion.jpg", gray)
gray = cv2.bilateralFilter(gray, 11, 17, 17)
cv2.imwrite("output/bilateralfilter.jpg", gray)
edged = cv2.Canny(gray, 170, 200)
cv2.imwrite("output/cannyedges.jpg", edged)
cnts= cv2.findContours(edged.copy(), cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts=sorted(cnts, key = cv2.contourArea, reverse = True)[:30]
NumberPlateCnt = None
count = 0
for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
if len(approx) == 4:
NumberPlateCnt = approx
break
# Masking the part other than the number plate
mask = np.zeros(gray.shape,np.uint8)
new_image = cv2.drawContours(mask,[NumberPlateCnt],0,255,-1)
new_image = cv2.bitwise_and(img,img,mask=mask)
cv2.imwrite("output/masked.jpg", new_image)
# Configuration for tesseract
config = ('-l eng --oem 1 --psm 3')
# Run tesseract OCR on image
text = pytesseract.image_to_string(new_image, config=config)
print(text)
cv2.waitKey(0)
return text
when i pass this image as image.jpg it returns the numbers in the plate
But, passing an image like this doesn't
In this case the isolation of the plate doesn't work, it masks almost everything, while
using other images the plate gets isolated but pytesseract still can't convert them to text(see last image)
what am i doing wrong?

How do I not get blobs of a certain size displayed? (OpenCV, Python)

I am in need of a function in OpenCV that allows me to not show blobs of a certain size, like in the picture where blobs are marked with a red circle, I would like for them simply not to be shown in an image.
This is the code I used:
img = cv.imread('Fotos/1.jpg')
params = cv.SimpleBlobDetector_Params()
params.filterByArea = True
params.minArea = 8200
params.maxArea = 15500
detector = cv.SimpleBlobDetector_create(params)
keypoints = detector.detect(img)
#draw blobs
img_with_blobs = cv.drawKeypoints(img, keypoints, np.array([]), (0, 0, 255), cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
plt.imshow(img_with_blobs)
cv.imshow("Keypoints", img_with_blobs)
Blobs detected
import cv2
img = cv2.imread('input/1.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 51, 9)
cnts = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
if 8200 < cv2.contourArea(c) < 12500:
cv2.drawContours(img, [c], -1, (255, 255, 255), -1)
cv2.imshow("1", img)
erased result

Unable to count objects in image using opencv python

I used below code for find cigarettes count in the below image using opencv python, but its not worked. Only this code finding some places only. i don't know what is the issue.. please help me
import numpy as np
import cv2
from PIL import Image
import sys
Path='D:\Artificial intelligence\Phyton'
filename='Test.png'
img = cv2.imread('D:\Artificial intelligence\Phyton\Test.png')
img1 = cv2.imread('D:\Artificial intelligence\Phyton\Test.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY)
img[thresh == 255] = 0
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
erosion = cv2.erode(img, kernel, iterations = 1)
cv2.imwrite('D:\Artificial intelligence\Phyton\Test112.png',erosion)
def findcircles(img,contours):
minArea = 300;
minCircleRatio = 0.5;
for contour in contours:
(x,y),radius = cv2.minEnclosingCircle(contour)
center = (int(x),int(y))
radius = int(radius)
if radius > 5:
continue;
cv2.circle(img1, center, 1, (191, 255, 0), 2)
cv2.imwrite('D:\Artificial intelligence\Phyton\Test11234.png',img1)
img = cv2.imread("D:\Artificial intelligence\Phyton\Test112.png")
cv2.imwrite('D:\Artificial intelligence\Phyton\org.png',img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,threshold = cv2.threshold(gray, 199, 255,cv2.THRESH_BINARY_INV)
cv2.imwrite('D:\Artificial intelligence\Phyton\threshold.png',threshold)
blur = cv2.medianBlur(gray,7)
cv2.imwrite('D:\Artificial intelligence\Phyton\blur.png',blur)
laplacian=cv2.Laplacian(blur,-1,ksize = 5,delta = -50)
cv2.imwrite('D:\Artificial intelligence\Phyton\laplacian.png',laplacian)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7))
dilation = cv2.dilate(laplacian,kernel,iterations = 1)
cv2.imwrite('D:\Artificial intelligence\Phyton\dilation.png',dilation)
result= cv2.subtract(threshold,dilation)
cv2.imwrite('D:\Artificial intelligence\Phyton\result.png',result)
contours, hierarchy = cv2.findContours(result,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
findcircles(gray,contours)
Image :
enter image description here
My result:
enter image description here

Python opencv Defect detection

I am trying to detect foreign substances in a round circle using opencv.
However, if the threshold is increased, the area around the circle is distorted, and if the threshold is decreased, foreign matter cannot be detected. Is there a way to detect foreign matter well while maintaining the circle?
import cv2
import cv2 as cv
import numpy as np
def roiSetting():
img = cv2.imread('img.jpg')
x = 100; y = 10;
w = 700; h = 600;
img_roi = img[400:1250,600:1450] #[colStart:colEnd, rowStart:rowEnd]
cv2.imwrite("3_roi_img.jpg", img_roi)
return img_roi
def imgCvt():
print("imgCvt in")
roi_img = roiSetting()
bgr_img = cv2.cvtColor(roi_img,cv2.COLOR_RGB2BGR) #RGB->BGR convert
bila_img = cv2.bilateralFilter(bgr_img,9,100,100) #bilaterafilter apply
r,g,b=cv2.split(bila_img) #split
merge_img=cv2.merge((r,g,b)) #merge
gray_img = cv2.cvtColor(merge_img,cv2.COLOR_RGB2GRAY) #RGB->GRAY convert
ret,thresh_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY) #threshold apply
equalize_img = cv2.equalizeHist(thresh_img) #Histogram equlization
canny_img = cv2.Canny(equalize_img,250,255) #Canny edge
kernel = np.ones((2,2), np.uint8)
dilate_img = cv2.dilate(canny_img, kernel, iterations = 1) # img dilate
new, contours, hierarchy = cv2.findContours(dilate_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours= sorted(contours, key = cv2.contourArea, reverse = True)[:10] #sorting
print(contours)
c = contours[0]
mask = np.zeros(roi_img.shape,np.uint8) #mask create(roi_img.shape)
cont_image = cv2.drawContours(mask, [c], -1, (255, 255, 255), -1) #background remove
con_gray_img = cv2.cvtColor(cont_image, cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(con_gray_img, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)
last_img = cv2.bitwise_and(roi_img, roi_img, mask = thresh1)
kernel = np.ones((3,3), np.uint8)
src = cv2.erode(last_img, kernel, iterations = 2)
gray = cv2.cvtColor(src, cv2.COLOR_RGB2GRAY)
rt1, dst1 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)
rt1, dst2 = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
_, contour1, _ = cv.findContours(dst2, cv2.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
for cnt in contour1:
cv2.drawContours(roi_img, [cnt], 0, (255, 0, 0), 2, cv2.LINE_8)
cv2.imshow('cont_roi.jpg', roi_img)
cv2.waitKey()
cv2.destroyAllWindows()
if __name__ == '__main__':
imgCvt()

OpenCV Background Subtraction Get Color Objects (Python)

Background subtraction method (BackgroundSubtractorMOG2) will normally return the output in binary image.
Is there a solution on how I can get the original colour of the object after implementing the BackgroundSubtractorMOG2 ?
import cv2
import numpy as np
cap = cv2.VideoCapture("people.mkv")
kernel_dil = np.ones((10,10), np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
fgbg = cv2.createBackgroundSubtractorMOG2(history=0, varThreshold=444, detectShadows=False)
while True:
ret, frame1 = cap.read()
frame = cv2.resize(frame1,(1364,700),fx=0,fy=0, interpolation = cv2.INTER_CUBIC)
mask = np.zeros(frame.shape, dtype=np.uint8)
mask.fill(255)
roi_corners = np.array([[(11,652), (1353,652), (940,84), (424,84)]], dtype=np.int32)
cv2.fillPoly(mask, roi_corners, 0)
masking = cv2.bitwise_or(frame, mask)
if ret == True:
fgmask = fgbg.apply(masking,mask)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
dilation = cv2.dilate(fgmask2, kernel_dil, iterations = 1)
(contours,hierarchy) = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for pic, contour in enumerate(contours):
area = cv2.contourArea(contour)
x,y,w,h = cv2.boundingRect(contour)
if(area>0.001):
cv2.rectangle(frame, (x,y), (x+w,y+h), (0,0,255), 2)
cv2.putText(frame, 'People', (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), 2, cv2.LINE_AA)
cv2.imshow("FullScreen", frame)
cv2.imshow("FGMask1", fgmask)
cv2.imshow("FGMask2", dilation)
key = cv2.waitKey(12)
if key == ord("q"):
break
If you consider the output as binary mask, you could just do a bitwise and with your original image
cv.bitwise_and(input, input, mask = yourMOG_output);

Categories

Resources