I'm trying to write a code that identifies the eyes of parakeets. So far, i have managed to use a code that identifies the circles edges and got great results at a certain threshold. But i can't save the result image.
I've tried using imwrite('result.png', clone) to save the result at the end of the code, but when I run it I'm get TypeError: Expected cv::UMat for argument 'img'.
I need the clone image to be colored too, but I've no idea where to start.
import cv2
import numpy as np
import imutils
def nothing(x):
pass
# Load an image
img = cv2.imread('sample.png')
# Resize The image
if img.shape[1] > 600:
img = imutils.resize(img, width=600)
# Create a window
cv2.namedWindow('Treshed')
# create trackbars for treshold change
cv2.createTrackbar('Treshold','Treshed',0,255,nothing)
while(1):
# Clone original image to not overlap drawings
clone = img.copy()
# Convert to gray
gray = cv2.cvtColor(clone, cv2.COLOR_BGR2GRAY)
# get current positions of four trackbars
r = cv2.getTrackbarPos('Treshold','Treshed')
# Thresholding the gray image
ret,gray_threshed = cv2.threshold(gray,r,255,cv2.THRESH_BINARY)
# Blur an image
bilateral_filtered_image = cv2.bilateralFilter(gray_threshed, 5, 175, 175)
# Detect edges
edge_detected_image = cv2.Canny(bilateral_filtered_image, 75, 200)
# Find contours
contours, _= cv2.findContours(edge_detected_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour_list = []
for contour in contours:
# approximte for circles
approx = cv2.approxPolyDP(contour,0.01*cv2.arcLength(contour,True),True)
area = cv2.contourArea(contour)
if ((len(approx) > 8) & (area > 30) ):
contour_list.append(contour)
# Draw contours on the original image
cv2.drawContours(clone, contour_list, -1, (255,0,0), 2)
# there is an outer boundary and inner boundary for each eadge, so contours double
print('Number of found circles: {}'.format(int(len(contour_list)/2)))
#Displaying the results
cv2.imshow('Objects Detected', clone)
cv2.imshow("Treshed", gray_threshed)
# ESC to break
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
# close all open windows
cv2.destroyAllWindows()
I just tried this modification and it works flawlessly.
# ESC to break
k = cv2.waitKey(1) & 0xFF
if k == 27:
cv2.imwrite('result.png', clone)
break
There's either a misconception about when/where to call imwrite or something is messy with your python/opencv version. I ran it in pycharm using python 3.6.8 and opencv-python 4.0.0.21
Related
import numpy as np
import cv2
import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import tensorflow as tf
model = tf.keras.models.load_model(r"C:\Users\ASUS\best_model_dataflair3.h5")
background = None
accumulated_weight = 0.5
ROI_top = 100
ROI_bottom = 300
ROI_right = 150
ROI_left = 350
def cal_accum_avg(frame, accumulated_weight):
global background
if background is None:
background = frame.copy().astype("float")
return None
cv2.accumulateWeighted(frame, background, accumulated_weight)
def segment_hand(frame, threshold=25):
global background
diff = cv2.absdiff(background.astype("uint8"), frame)
_ , thresholded = cv2.threshold(diff, threshold, 255, cv2.THRESH_BINARY)
#Fetching contours in the frame (These contours can be of hand or any other object in foreground) ...
image, contours, hierarchy = cv2.findContours(thresholded.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# If length of contours list = 0, means we didn't get any contours...
if len(contours) == 0:
return None
else:
# The largest external contour should be the hand
hand_segment_max_cont = max(contours, key=cv2.contourArea)
# Returning the hand segment(max contour) and the thresholded image of hand...
return (thresholded, hand_segment_max_cont)
cam = cv2.VideoCapture(0)
num_frames = 0
while True:
ret,frame = cam.read()
# filpping the frame to prevent inverted image of captured frame...
frame = cv2.flip(frame, 1)
frame_copy = frame.copy()
# ROI from the frame
roi = frame[ROI_top:ROI_bottom, ROI_right:ROI_left]
gray_frame = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
gray_frame = cv2.GaussianBlur(gray_frame, (9, 9), 0)
if num_frames < 70:
cal_accum_avg(gray_frame, accumulated_weight)
cv2.putText(frame_copy, "FETCHING BACKGROUND...PLEASE WAIT", (80, 400), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,0,255), 2)
else:
# segmenting the hand region
hand = segment_hand(gray_frame)
# Checking if we are able to detect the hand...
if hand is not None:
thresholded, hand_segment = hand
# Drawing contours around hand segment
cv2.drawContours(frame_copy, [hand_segment + (ROI_right, ROI_top)], -1, (255, 0, 0),1)
cv2.imshow("Thesholded Hand Image", thresholded)
thresholded = cv2.resize(thresholded, (64, 64))
thresholded = cv2.cvtColor(thresholded, cv2.COLOR_GRAY2RGB)
thresholded = np.reshape(thresholded, (1,thresholded.shape[0],thresholded.shape[1],3))
pred = model.predict(thresholded)
cv2.putText(frame_copy, word_dict[np.argmax(pred)], (170, 45), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
# Draw ROI on frame_copy
cv2.rectangle(frame_copy, (ROI_left, ROI_top), (ROI_right, ROI_bottom), (255,128,0), 3)
# incrementing the number of frames for tracking
num_frames += 1
# Display the frame with segmented hand
cv2.putText(frame_copy, "DataFlair hand sign recognition_ _ _", (10, 20), cv2.FONT_ITALIC, 0.5, (51,255,51), 1)
cv2.imshow("Sign Detection", frame_copy)
# Close windows with Esc
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
cam.release()
cv2.destroyAllWindows()
This is the code for predicting the hand gesture but camera is not opening. The code is running continuously but not showing any error.
Please anyone reslove this issue. This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN)to use the following CPU instructions in performance-critical operations:
I am getting this in anaconda prompt
I am using a standard 640x480 webcam. I have done Camera calibration in OpenCV in Python 3. This the Code I am using. The code is working and giving me the Camera Matrix and Distortion Coefficients successfully.
Now, How can I find how many millimeters are there in 640 pixels in my scene image. I have attached the webcam above a table horizontally and on the table, a Robotic arm is placed. Using the camera I am finding the centroid of an object. Using Camera Matrix my goal is to convert the location of that object (e.g. 300x200 pixels) to the millimeter units so that I can give the millimeters to the robotic arm to pick that object.
I have searched but not find any relevant information.
Please tell me that is there any equation or method for that. Thanks a lot!
import numpy as np
import cv2
import yaml
import os
# Parameters
#TODO : Read from file
n_row=4 #Checkerboard Rows
n_col=6 #Checkerboard Columns
n_min_img = 10 # number of images needed for calibration
square_size = 40 # size of each individual box on Checkerboard in mm
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) # termination criteria
corner_accuracy = (11,11)
result_file = "./calibration.yaml" # Output file having camera matrix
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(n_row-1,n_col-1,0)
objp = np.zeros((n_row*n_col,3), np.float32)
objp[:,:2] = np.mgrid[0:n_row,0:n_col].T.reshape(-1,2) * square_size
# Intialize camera and window
camera = cv2.VideoCapture(0) #Supposed to be the only camera
if not camera.isOpened():
print("Camera not found!")
quit()
width = int(camera.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))
cv2.namedWindow("Calibration")
# Usage
def usage():
print("Press on displayed window : \n")
print("[space] : take picture")
print("[c] : compute calibration")
print("[r] : reset program")
print("[ESC] : quit")
usage()
Initialization = True
while True:
if Initialization:
print("Initialize data structures ..")
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
n_img = 0
Initialization = False
tot_error=0
# Read from camera and display on windows
ret, img = camera.read()
cv2.imshow("Calibration", img)
if not ret:
print("Cannot read camera frame, exit from program!")
camera.release()
cv2.destroyAllWindows()
break
# Wait for instruction
k = cv2.waitKey(50)
# SPACE pressed to take picture
if k%256 == 32:
print("Adding image for calibration...")
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(imgGray, (n_row,n_col),None)
# If found, add object points, image points (after refining them)
if not ret:
print("Cannot found Chessboard corners!")
else:
print("Chessboard corners successfully found.")
objpoints.append(objp)
n_img +=1
corners2 = cv2.cornerSubPix(imgGray,corners,corner_accuracy,(-1,-1),criteria)
imgpoints.append(corners2)
# Draw and display the corners
imgAugmnt = cv2.drawChessboardCorners(img, (n_row,n_col), corners2,ret)
cv2.imshow('Calibration',imgAugmnt)
cv2.waitKey(500)
# "c" pressed to compute calibration
elif k%256 == 99:
if n_img <= n_min_img:
print("Only ", n_img , " captured, ", " at least ", n_min_img , " images are needed")
else:
print("Computing calibration ...")
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, (width,height),None,None)
if not ret:
print("Cannot compute calibration!")
else:
print("Camera calibration successfully computed")
# Compute reprojection errors
for i in range(len(objpoints)):
imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
tot_error += error
print("Camera matrix: ", mtx)
print("Distortion coeffs: ", dist)
print("Total error: ", tot_error)
print("Mean error: ", np.mean(error))
# Saving calibration matrix
try:
os.remove(result_file) #Delete old file first
except Exception as e:
#print(e)
pass
print("Saving camera matrix .. in ",result_file)
data={"camera_matrix": mtx.tolist(), "dist_coeff": dist.tolist()}
with open(result_file, "w") as f:
yaml.dump(data, f, default_flow_style=False)
# ESC pressed to quit
elif k%256 == 27:
print("Escape hit, closing...")
camera.release()
cv2.destroyAllWindows()
break
# "r" pressed to reset
elif k%256 ==114:
print("Reset program...")
Initialization = True
This the Camera Matrix:
818.6 0 324.4
0 819.1 237.9
0 0 1
Distortion coeffs:
0.34 -5.7 0 0 33.45
I was actually thinking that you should be able to solve your problem in a simple way:
mm_per_pixel = real_mm_width : 640px
Assuming that the camera initially moves in parallel to the plan with the object to pick [i.e. fixed distance], real_mm_width can be found measuring the physical distance corresponding to those 640 pixels of your picture. For the sake of an example say that you find that real_mm_width = 32cm = 320mm, so you get mm_per_pixel = 0.5mm/px. With a fixed distance this ratio doesn't change
It seems also the suggestion from the official documentation:
This consideration helps us to find only X,Y values. Now for X,Y
values, we can simply pass the points as (0,0), (1,0), (2,0), ...
which denotes the location of points. In this case, the results we get
will be in the scale of size of chess board square. But if we know the
square size, (say 30 mm), we can pass the values as (0,0), (30,0),
(60,0), ... . Thus, we get the results in mm
Then you just need to convert the centroid coordinates in pixels [e.g. (pixel_x_centroid, pixel_y_centroid) = (300px, 200px)] to mm using:
mm_x_centroid = pixel_x_centroid * mm_per_pixel
mm_y_centroid = pixel_y_centroid * mm_per_pixel
which would give you the final answer:
(mm_x_centroid, mm_y_centroid) = (150mm, 100mm)
Another way to see the same thing is this proportion where the first member is the measurable/known ratio:
real_mm_width : 640px = mm_x_centroid : pixel_x_centroid = mm_y_centroid = pixel_y_centroid
I want to count vehicles when the rectangle touches(intersects) the line. I don't know more about counting objects in video frame. Based on my pre-search, I have found out some useful information such as centroid, euclidean distance and etc. But, i don't have much knowledge about the geometry math behind it. Here is an example video. https://www.youtube.com/watch?v=z1Cvn3_4yGo. I think they used the same method.
I have got the center of the rectangle and drawn a red line across the road. Now I want to count vehicles when it touches the line. Bellow, I have uploaded my current output of the system in a image format as well as my current code.
# import the necessary packages
from imutils.video import VideoStream
from imutils.video import FPS
import argparse
import imutils
import time
import cv2
tracker = cv2.TrackerCSRT_create()
vs = cv2.VideoCapture("Video.mp4")
initBB = None
# loop over frames from the video stream
while vs.isOpened():
ret,frame = vs.read()
cv2.line(frame, (933 , 462), (1170 , 462), (0,0,255), 3)
# check to see if we are currently tracking an object
if initBB is not None:
# grab the new bounding box coordinates of the object
(success, box) = tracker.update(frame)
# check to see if the tracking was a success
if success:
(x, y, w, h) = [int(v) for v in box]
cv2.rectangle(frame, (x, y), (x + w, y + h),
(0, 255, 0), 2)
cX = int((x + x+w) / 2.0)
cY = int((y + y+h) / 2.0)
cv2.circle(frame, (cX, cY), 4, (255, 0, 0), -1)
# show the output frame
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("s"):
# select the bounding box of the object we want to track (make
# sure you press ENTER or SPACE after selecting the ROI)
initBB = cv2.selectROI("Frame", frame, fromCenter=False,
showCrosshair=True)
# start OpenCV object tracker using the supplied bounding box
# coordinates, then start the FPS throughput estimator as well
tracker.init(frame, initBB)
fps = FPS().start()
# if the `q` key was pressed, break from the loop
elif key == ord("q"):
break
else:
vs.release()
cv2.destroyAllWindows()
You should just check whether the lower two x axis points of your bonding box are greater than or equal to the x axis points of the line
I am learning Image Filtering using opencv. I wrote some code but my code could only detect objects with red color, How can I detect objects with other colors.
I tried different numpy array values, still I'm not satisfied with output
hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
lower_blue = np.array([150,150,0])
upper_blue = np.array([255,255,225])
mask = cv2.inRange(hsv,lower_blue,upper_blue)
res = cv2.bitwise_and(frame,frame,mask=mask)
cv2.imshow('res',res)
You just need to change the boundary values (in your case lower_blue and upper_blue) to different values. The values may range ass follows [0 < H< 179], [0 < S < 255], [0 < V < 255]. You can see it better from the picture.
Good luck!
First, the range of H should be from 0 to 179. To get the feeling of what combination of HSV values produces what color here is a small piece of code. Below code creates trackbars for H, S, V. Adjust the trackbars to segment the different colors.
import cv2
import numpy as np
def nothing(x):
pass
cap = cv2.VideoCapture(0)
# Create a window
cv2.namedWindow('image',cv2.WINDOW_NORMAL)
# create trackbars for color change
cv2.createTrackbar('lowH','image',0,179,nothing)
cv2.createTrackbar('highH','image',179,179,nothing)
cv2.createTrackbar('lowS','image',0,255,nothing)
cv2.createTrackbar('highS','image',255,255,nothing)
cv2.createTrackbar('lowV','image',0,255,nothing)
cv2.createTrackbar('highV','image',255,255,nothing)
while(True):
ret, frame = cap.read()
# get current positions of the trackbars
ilowH = cv2.getTrackbarPos('lowH', 'image')
ihighH = cv2.getTrackbarPos('highH', 'image')
ilowS = cv2.getTrackbarPos('lowS', 'image')
ihighS = cv2.getTrackbarPos('highS', 'image')
ilowV = cv2.getTrackbarPos('lowV', 'image')
ihighV = cv2.getTrackbarPos('highV', 'image')
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_hsv = np.array([ilowH, ilowS, ilowV])
higher_hsv = np.array([ihighH, ihighS, ihighV])
mask = cv2.inRange(hsv, lower_hsv, higher_hsv)
frame = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('image', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
gray = cv2.cvtColor(image_frame, cv2.COLOR_BGR2GRAY) cv2.error: /home/pi/Downloads/opencv/modules/imgproc/src/color.cpp:11095: error: (-215) scn == 3 || scn == 4 in function cvtColor.
Is there anyway to solve it without changing the picam?
# Import OpenCV2 for image processing
import cv2
# Start capturing video
vid_cam = cv2.VideoCapture(0)
# Detect object in video stream using Haarcascade Frontal Face
face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# For each person, one face id
face_id = 5
# Initialize sample face image
count = 0
# Start looping
while(True):
# Capture video frame
_, image_frame = vid_cam.read()
# Convert frame to grayscale
gray = cv2.cvtColor(image_frame, cv2.COLOR_BGR2GRAY)
# Detect frames of different sizes, list of faces rectangles
faces = face_detector.detectMultiScale(gray, 1.3, 5)
# Loops for each faces
for (x,y,w,h) in faces:
# Crop the image frame into rectangle
cv2.rectangle(image_frame, (x,y), (x+w,y+h), (255,0,0), 2)
# Increment sample face image
count += 1
# Save the captured image into the datasets folder
cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])
# Display the video frame, with bounded rectangle on the person's face
cv2.imshow('frame', image_frame)
# To stop taking video, press 'q' for at least 100ms
if cv2.waitKey(100) & 0xFF == ord('q'):
break
# If image taken reach 100, stop taking video
elif count>100:
break
# Stop video
vid_cam.release()
# Close all started windows
cv2.destroyAllWindows()code here
If you are using picam,
then you have to import the picam module
import picamera
def getFrame():
jpegBuffer = io.BytesIO()
webcam.capture(jpegBuffer, format='jpeg')
buff = numpy.fromstring(jpegBuffer.getvalue(), dtype=numpy.uint8)
return cv2.imdecode(buff, 1)
image_frame = getFrame()
try this once,