Dlib + OpenCV Draw Points Landsmark - python

I would like to draw contour of the cheek, as in the image below:
I am using OpenCV and Dlib to detect the landmarks, And I do not know how to manipulate the Dlib points. Does anyone know how I can make the contour on the cheek?
Here is my code:
import cv2
import dlib
import numpy as np
def imprimePontos (imagem, pontosFaciais):
for p in pontosFaciais.parts():
cv2.circle(imagem, (p.x, p.y), 2, (0, 255,0) ,4)
def imprimeNumeros (imagem, pontosFaciais):
for i, p in enumerate (pontosFaciais.parts()):
cv2.putText(imagem, str(i), (p.x, p.y), fonte, .55, (0, 0, 255),1)
def points (imagem, pontosFaciais): #here where a draw de points
p68 =[[15, 47, False],
[47, 28, False],
[28, 30, False],
[30, 12, False]]
for k in range(0, len(p68)):
pontos = []
for i in range(p68[k] [0], p68[k][1] + 1):
ponto = [pontosFaciais.part(i).x, pontosFaciais.part(i).y]
pontos.append(ponto)
pontos = np.array(pontos, dtype=np.int32)
cv2.polylines(imagem, [pontos], p68 [k][2], (255, 0, 0), 2)
fonte = cv2.FONT_HERSHEY_COMPLEX_SMALL
imagem = cv2.imread('1.jpg')
detectorface = dlib.get_frontal_face_detector()
detectorpontosfaciais =
dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
facesDetectadas = detectorface(imagem, 2)
for face in facesDetectadas:
pontos = detectorpontosfaciais(imagem, face)
print(pontos.parts())
#imprimePontos(imagem, pontos)
#imprimeNumeros(imagem, pontos)
points(imagem, pontos)
cv2.imshow("Bucheca", imagem)
cv2.waitKey()
cv2.destroyAllWindows()
This is my output:

One fast non-optimized approach based on Adrian Rosebrock's blog post https://www.pyimagesearch.com/2017/04/10/detect-eyes-nose-lips-jaw-dlib-opencv-python/:
from collections import OrderedDict
import numpy as np
import cv2
import dlib
import imutils
CHEEK_IDXS = OrderedDict([("left_cheek", (1,2,3,4,5,48,49,31)),
("right_cheek", (11,12,13,14,15,35,53,54))
])
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
img = cv2.imread('tom.jpg')
img = imutils.resize(img, width=600)
overlay = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
detections = detector(gray, 0)
for k,d in enumerate(detections):
shape = predictor(gray, d)
for (_, name) in enumerate(CHEEK_IDXS.keys()):
pts = np.zeros((len(CHEEK_IDXS[name]), 2), np.int32)
for i,j in enumerate(CHEEK_IDXS[name]):
pts[i] = [shape.part(j).x, shape.part(j).y]
pts = pts.reshape((-1,1,2))
cv2.polylines(overlay,[pts],True,(0,255,0),thickness = 2)
cv2.imshow("Image", overlay)
cv2.waitKey(0)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
Output Image:

Related

Using opencv to mask the background

I'm trying to use tesseract to read text from a game with poor results.
What I would like to accomplish is to remove the background from the image so that only the text is visible to improve OCR results.
I've tried cv2.inRange, thresholding yet I can't seem to get it to work.
import numpy as np
import pytesseract
from tesserocr import PyTessBaseAPI, OEM
def _img_to_bytes(image: np.ndarray, colorspace: str = 'LAB'):
# Sets an OpenCV-style image for recognition: https://github.com/sirfz/tesserocr/issues/198
bytes_per_pixel = image.shape[2] if len(image.shape) == 3 else 1
height, width = image.shape[:2]
bytes_per_line = bytes_per_pixel * width
if bytes_per_pixel != 1 and colorspace != 'RGB':
# non-RGB color image -> convert to RGB
image = cv2.cvtColor(image, getattr(cv2, f'COLOR_{colorspace}2RGB'))
elif bytes_per_pixel == 1 and image.dtype == bool:
# binary image -> convert to bitstream
image = np.packbits(image, axis=1)
bytes_per_line = image.shape[1]
width = bytes_per_line * 8
bytes_per_pixel = 0
# else image already RGB or grayscale
return image.tobytes(), width, height, bytes_per_pixel, bytes_per_line
img = cv2.imread("ref.png")
img = ~img
clahe = cv2.createCLAHE(clipLimit=3., tileGridSize=(8,8))
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
l2 = clahe.apply(l)
lab = cv2.merge((l2,a,b))
img = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
with PyTessBaseAPI(psm=3, oem=OEM.LSTM_ONLY, path=f"ocr", lang=d2r ) as api:
api.ReadConfigFile("ocr/config.txt")
api.SetVariable("user_words_file","ocr/dict.txt")
api.SetImageBytes(*_img_to_bytes(img))
print(api.GetUTF8Text())
cv2.imshow('res',img)
cv2.waitKey()```
Inverting color may help? try this & let me know.
import cv2
image = cv2.imread("Bytelock.jpg")
image = ~image
cv2.imwrite("Bytelock.jpg",image)
Inverted image
Red varient
import numpy as np
import imutils
import cv2
img_rgb = cv2.imread('ss.jpg')
Conv_hsv_Gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY_INV |cv2.THRESH_OTSU)
img_rgb[mask == 255] = [0, 0, 255]
cv2.imshow("red", img_rgb)
cv2.imwrite("red.jpg", img_rgb)
More sharpen? Try
import numpy as np
import imutils
import cv2
img_rgb = cv2.imread('ss.jpg')
Conv_hsv_Gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY_INV |cv2.THRESH_OTSU)
img_rgb[mask == 255] = [0, 0, 255]
cv2.imwrite("mask.jpg", mask)
cv2.imshow("mask", mask) # show windows
cv2.waitKey(0)
**
Much more better option
**
import cv2
image = cv2.imread("ss1.jpg")
image = ~image
img = image
clahe = cv2.createCLAHE(clipLimit=3., tileGridSize=(8,8))
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
l2 = clahe.apply(l)
lab = cv2.merge((l2,a,b))
img2 = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
cv2.imshow('Increased contrast', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
More sharpen

cant see point marker on rviz ros

my aim is to follow a green ball with the camera and show the movements of this ball in the view. To do this, I marked the middle of the ball with a marker, but I can't see it in the rviz. The code or rviz does not give any errors, and I am able to visualize /webcam topic but markers dont show up. What could be the problem? I am using ros neotic Thank you
'''
#!/usr/bin/env python3
import rospy
from sensor_msgs.msg import Image
import cv2
import numpy as np
from cv_bridge import CvBridge, CvBridgeError
import sys
from collections import deque
from imutils.video import VideoStream
from visualization_msgs.msg import Marker, MarkerArray
from geometry_msgs.msg import Point
import gc
import argparse
import time
import imutils
def camdet():
bridge = CvBridge()
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", help="Path to the (optional) video file")
ap.add_argument("-b", "--buffer", default=64, type=int, help="max buffer size")
args = vars(ap.parse_args())
greenLower = (29, 86, 6)
greenUpper = (64, 255, 255)
pts = deque(maxlen=args["buffer"])
if not args.get("video", False):
vs = VideoStream(src=0).start()
else:
vs = cv2.VideoCapture(args["video"])
time.sleep(2.0)
rospy.init_node("object_detection",anonymous=True)
while True:
frame = vs.read()
frame = frame[1] if args.get("video", False) else frame
if frame is None:
break
frame = imutils.resize(frame, width=600)
blurred = cv2.GaussianBlur(frame, (11, 11), 0)
hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, greenLower, greenUpper)
mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)
cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
center = None
v = 0
if len(cnts) > 0:
c = max(cnts, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(c)
M = cv2.moments(c)
center = (int(M['m10']/M['m00']), int(M['m01']/M['m00']))
if radius > 10:
cv2.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2)
cv2.circle(frame, center, 5, (0, 0, 255), -1)
v += 1
pts.append(center)
marker = Marker()
marker.header.frame_id = "base_link"
marker.ns = "marked"
marker.id = 0
marker.type = marker.POINTS
marker.action = marker.ADD
marker.scale.x = 1
marker.scale.y = 1
marker.scale.z = 0.1
marker.pose.orientation.x = 0
marker.pose.orientation.y = 0
marker.pose.orientation.z= 0
marker.pose.orientation.w = 1
points = [0,0]
for i in range(v):
p = Point()
p.x = int(M['m10']/M['m00'])
p.y = int(M['m01']/M['m00'])
points.clear()
points.append(p)
marker.points = points
print(marker.points)
marker.pose.position.x = int(M['m10']/M['m00'])
marker.pose.position.y = int(M['m01']/M['m00'])
marker.color.a = 0.4
marker.color.r = 0.9
marker.color.g = 0.1
marker.color.b = 0.2
marker.lifetime = rospy.Duration()
img_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=10)
rate = rospy.Rate(10)
msg = bridge.cv2_to_imgmsg(frame, encoding="bgr8")
img_pub.publish(msg)
marker_pub = rospy.Publisher("marker", Marker, queue_size = 100)
marker_pub.publish(marker)
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
if not args.get("video", False):
vs.stop()
else:
vs.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
try:
camdet()
except rospy.ROSInterruptException:
pass
'''
ROS WIKI said "Don't forget to set color.a = 1 or your marker will be invisible!".

Unable to clip and save the ROI/bounding box in opencv python

Im trying to save only the rectangular ROI region from a video file into images. But the entire image is getting saved with the RED rectangular ROI box on it. What am I doing wrong here ?
I tried saving rect_img but thats giving error "!_img.empty() in function 'imwrite'" ,
and not saving any images at all.
The upper_left and bottom_right coordinates are for a 1920 X 1080p video, you wil have to adjust is as per your video resolution.
import cv2
from matplotlib import pyplot as plt
import imutils
import numpy as np
import pytesseract
cam_capture = cv2.VideoCapture('1080_EDIT.webm')
upper_left = (1400, 700)
bottom_right = (700, 1000)
ctr=1 #filename counter
while True:
_, image_frame = cam_capture.read()
ctr+=1
#Rectangle marker
r = cv2.rectangle(image_frame, upper_left, bottom_right, (100, 50, 200), 5)
rect_img = image_frame[upper_left[1] : bottom_right[1], upper_left[0] : bottom_right[0]]
cv2.imwrite("rect"+str(ctr)+".jpg",r)
#print (rect_img)
#img=cv2.imread(rect_img)
gray = cv2.cvtColor(r, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray, 13, 15, 15)
edged = cv2.Canny(gray, 30, 200)
contours = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:10]
screenCnt = None
for c in contours:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.018 * peri, True)
if len(approx) == 4:
screenCnt = approx
break
if screenCnt is None:
detected = 0
print ("No contour detected")
else:
detected = 1
if detected == 1:
cv2.drawContours(r, [screenCnt], -1, (0, 0, 255), 3)
cv2.imshow("image", image_frame)
if cv2.waitKey(1) % 256 == 27 :
break
cam_capture.release()
cv2.destroyAllWindows()
Solved it by
roi=r[700:1000,700:1400]
cv2.imwrite("rect"+str(ctr)+".jpg",roi)

Video Processing frame value can not using in main funtion in OpenCv Python

I want to use frame value array which including video loop but I can't get values from video processing function. What I want to do is to take the frame sequence values from the video function, then use those values in the main function. But both the while loop scope and the video function scope do not allow this. I'd appreciate it if you could help. Thank you from now.
def video_processing():
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
while True:
ret, frame = cap.read()
if ret == True :
cv2.imshow("Image", frame)
if cv2.waitKey(1) & 0xFF == 27 :
cap.release()
break
def main():
video_processing()
print frame #is not working!
if __name__ == '__main__':
main()
Update (Full Code)
import Tkinter as tk
import ttk
from ttk import Frame
import os
import time
from Tkinter import *
from Tkinter import Tk, Label
import cv2
import threading
import time
import imutils
import numpy as np
import matplotlib.pyplot as plt
from PIL import ImageTk, Image
from threading import Thread
Frames = []
def video_processing():
cap = cv2.VideoCapture(0)
# cap = cv2.VideoCapture("C:\Users\eren\OneDrive\Desktop\WIN_20190522_18_16_29_Pro.mp4")
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
global Frames
while True:
global Frames
ret, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
y , x = hsv.shape[:2] #x = 320 , y = 240
# Define 'brown' range in HSV colorspace
lower = np.array([10, 100, 20])
upper = np.array([20, 255, 200])
# Threshold the HSV image to get only brown color
mask1 = cv2.inRange(hsv, lower, upper)
kernel = np.ones((5,5),np.uint8)
thresh = cv2.dilate(mask1,kernel,iterations = 2)
# find contours in thresholded image, then grab the largest
# one
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)
# determine the most extreme points along the contour
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
cv2.drawContours(thresh, [c], -1, (0, 255, 255), 2)
cv2.circle(thresh, extLeft , 8, (0, 0, 255) , -1)
cv2.circle(thresh, extRight, 8, (0, 255, 0) , -1)
cv2.circle(thresh, extTop , 8, (255, 0, 0) , -1)
cv2.circle(thresh, extBot , 8, (255, 255, 0), -1)
x_center = (extLeft[0] + extRight[0] + extTop[0] + extBot[0])/4
y_center = (extLeft[1] + extRight[1] + extTop[1] + extBot[1])/4
cv2.circle(frame,(x_center, y_center), 3, (0,255,0), -1)
cv2.line(frame,(extLeft[0] ,0),(extLeft[0],y) ,(0,255,0),2) # y axis - binary
cv2.line(frame,(extRight[0],0),(extRight[0],y),(0,255,0),2) # y axis - binary
cv2.line(frame,(0,extTop[1]) ,(x,extTop[1]) ,(0,255,0),2) # x axis - binary
cv2.line(frame,(0,extBot[1]) ,(x,extBot[1]) ,(0,255,0),2) # x axis - binary
# cv2.imshow("mask" , thresh)
cv2.imshow("Image", frame)
Frames = frame
# print frame
# return frame
if cv2.waitKey(1) & 0xFF == 27 :
cap.release()
break
# return frame
def main():
global Frames
video_processing()
print Frames
# print a
if __name__ == '__main__':
main()
This works for me:
import cv2
frame = None
def video_processing():
global frame
cap = cv2.VideoCapture('VIDEO_NAME.mp4')
while True:
ret, frame = cap.read()
if ret == True :
cv2.imshow("Image", frame)
if cv2.waitKey(1) & 0xFF == 27 :
cap.release()
break
def main():
video_processing()
print(frame)
if __name__ == '__main__':
main()

Use grabcut algorithm to separate the saliency areas

enter image description hereI first detected the saliency of the image and then used the grabcut algorithm to segment the saliency targets. However, the result was a salient image but did not segment the saliency map. The error was as follows: error :-5 image mush have cv_8uc3 type in function grabcut, this is my source code, what should I do?`
import tensorflow as tf
import numpy as np
import os
from scipy import misc
import argparse
import sys,cv2
from skimage.io import imread, imsave
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
g_mean = np.array(([126.88,120.24,112.19])).reshape([1,1,3])
output_folder = "./test_output"
def rgba2rgb(img):
if img.ndim == 2:
img = gray2rgb(img)
elif img.shape[2] == 4:
img = img[:, :, :3]
upper_dim = max(img.shape[:2])
if upper_dim > args.max_dim:
img = rescale(img, args.max_dim/float(upper_dim), order=3)
return img
def largest_contours_rect(saliency):
contours, hierarchy = cv2.findContours(saliency * 3,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key = cv2.contourArea)
return cv2.boundingRect(contours[-1])
def refine_saliency_with_grabcut(img, saliency):
rect = largest_contours_rect(saliency)
bgdmodel = np.zeros((1, 65),np.float64)
fgdmodel = np.zeros((1, 65),np.float64)
saliency[np.where(saliency > 0)] = cv2.GC_FGD
mask = saliency
cv2.grabCut(img, mask, rect, bgdmodel, fgdmodel, 1, cv2.GC_INIT_WITH_RECT)
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
return mask
def backprojection_saliency(img,args):
saliency =main(args)
#cv2.imshow("original", saliency)
#saliency=mpimg.imread('alpha1.png')
img = cv2.resize(img, (320, 232))
mask = refine_saliency_with_grabcut(img, saliency)
#misc.imsave(os.path.join(output_folder,'flowers2.png'),result)
return mask
def main(args):
if not os.path.exists(output_folder):
os.mkdir(output_folder)
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction = args.gpu_fraction)
with tf.Session(config=tf.ConfigProto(gpu_options = gpu_options)) as sess:
saver = tf.train.import_meta_graph('./meta_graph/my-model.meta')
saver.restore(sess,tf.train.latest_checkpoint('./salience_model'))
image_batch = tf.get_collection('image_batch')[0]
pred_mattes = tf.get_collection('mask')[0]
if args.rgb_folder:
rgb_pths = os.listdir(args.rgb_folder)
for rgb_pth in rgb_pths:
rgb = misc.imread(os.path.join(args.rgb_folder,rgb_pth))
if rgb.shape[2]==4:
rgb = rgba2rgb(rgb)
origin_shape = rgb.shape
rgb = np.expand_dims(misc.imresize(rgb.astype(np.uint8),[320,320,3],interp="nearest").astype(np.float32)-g_mean,0)
feed_dict = {image_batch:rgb}
pred_alpha = sess.run(pred_mattes,feed_dict = feed_dict)
final_alpha = misc.imresize(np.squeeze(pred_alpha),origin_shape)
misc.imsave(os.path.join(output_folder,rgb_pth),final_alpha)
else:
rgb = misc.imread(args.rgb)
if rgb.shape[2]==4:
rgb = rgba2rgb(rgb)
origin_shape = rgb.shape[:2]
rgb = np.expand_dims(misc.imresize(rgb.astype(np.uint8),[320,320,3],interp="nearest").astype(np.float32)-g_mean,0)
feed_dict = {image_batch:rgb}
pred_alpha = sess.run(pred_mattes,feed_dict = feed_dict)
final_alpha = misc.imresize(np.squeeze(pred_alpha),origin_shape)
misc.imsave(os.path.join(output_folder,'alpha.png'),final_alpha)
#rgbs = mpimg.imread('flower1.jpg')
result=refine_saliency_with_grabcut(rgb, final_alpha)
misc.imsave(os.path.join(output_folder,'segmentation.png'),result)
#cv2.imshow("original", final_alpha)
#plt.imshow(final_alpha)
return final_alpha;
def parse_arguments(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--rgb', type=str,
help='input rgb',default = None)
parser.add_argument('--rgb_folder', type=str,
help='input rgb',default = None)
parser.add_argument('--gpu_fraction', type=float,
help='how much gpu is needed, usually 4G is enough',default = 1.0)
return parser.parse_args(argv)
if __name__ == '__main__':
main(parse_arguments(sys.argv[1:]))``
I use the threshed binary image to find the max contour, then create a mask. Do grabcut using this mask.
The source:
And the result is like this:
#!/usr/bin/python3
# 2017.11.27 15:26:53 CST
# 2017.11.27 16:37:38 CST
import numpy as np
import cv2
## read the image(读取图像)
img = cv2.imread("tt04_flower.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#displaySplit(img)
## threshed(阈值化)
th, threshed = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
## findContours(查找轮廓)
cnts = cv2.findContours(threshed, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
## sorted by area(按照面积排序)
cnts = sorted(cnts, key=cv2.contourArea)
## get the maximum's boundinRect(获取最大边缘的外接矩形)
cnt = cnts[-1]
bbox = x,y,w,h = cv2.boundingRect(cnt)
## create mask(创建掩模)
mask = np.ones_like(gray, np.uint8)*cv2.GC_PR_BGD
cv2.drawContours(mask, [cnt], -1, cv2.GC_FGD, -1)
## 使用 grabcut 分割
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
rect = bbox
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)
mask2 = np.where((mask==2)|(mask==0),0,1).astype("uint8")
grabcut = img*mask2[:,:,np.newaxis]
## save and display
cv2.imwrite("flower_res.png", grabcut)
cv2.imshow("(1) source", img)
cv2.imshow("(2) grabcut", grabcut)
cv2.waitKey()

Categories