手势识别dataset在线生成

# organize imports
import cv2
import imutils
import numpy as np
from sklearn.metrics import pairwise

# global variables
bg = None

#-------------------------------------------------------------------------------
# Function - To find the running average over the background
#-------------------------------------------------------------------------------
def run_avg(image, accumWeight):
    global bg
    # initialize the background
    if bg is None:
        bg = image.copy().astype("float")
        return

    # compute weighted average, accumulate it and update the background
    cv2.accumulateWeighted(image, bg, accumWeight)

#-------------------------------------------------------------------------------
# Function - To segment the region of hand in the image
#-------------------------------------------------------------------------------
def segment(image, threshold=25):
    global bg
    # find the absolute difference between background and current frame
    diff = cv2.absdiff(bg.astype("uint8"), image)



    # threshold the diff image so that we get the foreground
    thresholded = cv2.threshold(diff, threshold, 255, cv2.THRESH_BINARY)[1]


    # get the contours in the thresholded image
    (_, cnts, _) = cv2.findContours(thresholded.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # return None, if no contours detected
    if len(cnts) == 0:
        return
    else:
        # based on contour area, get the maximum contour which is the hand
        segmented = max(cnts, key=cv2.contourArea)
        #生成mask
        #contour_image_gray = np.zeros(image.shape, dtype=np.uint8)
        #contour_image_gray = cv2.drawContours(contour_image_gray, cnts, segmented, (1, 1, 1), cv2.FILLED)
        #obj_image = image * contour_image_gray
        return (thresholded, segmented)


def calculateBoundImage(src_image):
    '''
    求取图像中的物体的边界矩形
    :param src_image: 源图像
    :return: 图像中的物体的边界矩形
    '''
    tmp_image = src_image.copy()
    #if (len(tmp_image.shape) == 3):
        #tmp_image = cv2.cvtColor(tmp_image, cv2.COLOR_BGR2GRAY)
    # tmp_image = cv2.blur(tmp_image, (51, 51))
    # 对图像进行二值化
    # ret, thresh_image = cv2.threshold(tmp_image, 120, 255, cv2.THRESH_BINARY_INV)
    thresh_image = cv2.adaptiveThreshold(tmp_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 71, 10)
    thresh_image = cv2.morphologyEx(thresh_image, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25)))
    # 寻找最外的轮廓
    ret_image, contours_ls, hierachy = cv2.findContours(thresh_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)
    pnt_cnt_ls = np.array([tmp_contour.shape[0] for tmp_contour in contours_ls])
    # contour_iamge_gray = np.zeros(tmp_image.shape, dtype=np.uint8)
    # contour_iamge_gray = cv2.drawContours(contour_iamge_gray, contours_ls, np.argmax(pnt_cnt_ls), 255, cv2.FILLED)
    # contour_iamge_gray = cv2.morphologyEx(contour_iamge_gray, cv2.MORPH_CROSS, np.ones(10,dtype=np.uint8))
    # ret, thresh_image = cv2.threshold(contour_iamge_gray, 122, 255, cv2.THRESH_BINARY)
    # ret_image, contours_ls, hierachy = cv2.findContours(thresh_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)
    contour_image = src_image.copy()
    contour_idx = np.argmax(pnt_cnt_ls)
    contour_image = cv2.drawContours(contour_image, contours_ls, contour_idx, (0, 0, 255))
    longest_contour = contours_ls[contour_idx]

    contour_image_gray = np.zeros(src_image.shape, dtype=np.uint8)
    contour_image_gray = cv2.drawContours(contour_image_gray, contours_ls, contour_idx, (1, 1, 1), cv2.FILLED)
    obj_image = src_image * contour_image_gray
    bound_box = cv2.boundingRect(longest_contour)
    return bound_box


#-------------------------------------------------------------------------------
# Function - 计算分割出来的轮廓中手指的个数
#-------------------------------------------------------------------------------
def count(thresholded, segmented):
	# find the convex hull of the segmented hand region
	chull = cv2.convexHull(segmented)

	# find the most extreme points in the convex hull
	extreme_top    = tuple(chull[chull[:, :, 1].argmin()][0])
	extreme_bottom = tuple(chull[chull[:, :, 1].argmax()][0])
	extreme_left   = tuple(chull[chull[:, :, 0].argmin()][0])
	extreme_right  = tuple(chull[chull[:, :, 0].argmax()][0])

	# find the center of the palm
	cX = (extreme_left[0] + extreme_right[0]) / 2
	cY = (extreme_top[1] + extreme_bottom[1]) / 2

	# find the maximum euclidean distance between the center of the palm
	# and the most extreme points of the convex hull
	distance = pairwise.euclidean_distances([(cX, cY)], Y=[extreme_left, extreme_right, extreme_top, extreme_bottom])[0]
	maximum_distance = distance[distance.argmax()]
	
	# calculate the radius of the circle with 80% of the max euclidean distance obtained
	radius = int(0.8 * maximum_distance)
	
	# find the circumference of the circle
	circumference = (2 * np.pi * radius)

	# take out the circular region of interest which has 
	# the palm and the fingers
	circular_roi = np.zeros(thresholded.shape[:2], dtype="uint8")
	
	# draw the circular ROI
	cv2.circle(circular_roi, (int(cX), int(cY)), int(radius), 255, 1)

	
	# take bit-wise AND between thresholded hand using the circular ROI as the mask
	# which gives the cuts obtained using mask on the thresholded hand image
	circular_roi = cv2.bitwise_and(thresholded, thresholded, mask=circular_roi)

	# compute the contours in the circular ROI
	(_, cnts, _) = cv2.findContours(circular_roi.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

	# initalize the finger count
	count = 0

	# loop through the contours found
	for c in cnts:
		# compute the bounding box of the contour
		(x, y, w, h) = cv2.boundingRect(c)

		# increment the count of fingers only if -
		# 1. The contour region is not the wrist (bottom area)
		# 2. The number of points along the contour does not exceed
		#     25% of the circumference of the circular ROI
		if ((cY + (cY * 0.25)) > (y + h)) and ((circumference * 0.25) > c.shape[0]):
			count += 1

	return count

#-------------------------------------------------------------------------------
# Main function
#-------------------------------------------------------------------------------
if __name__ == "__main__":
    # initialize accumulated weight
    accumWeight = 0.5

    # get the reference to the webcam
    camera = cv2.VideoCapture(0)

    # region of interest (ROI) coordinates
    top, right, bottom, left = 10, 380, 325, 630

    # initialize num of frames
    num_frames = 0

    # calibration indicator
    calibrated = False

    # keep looping, until interrupted
    while(True):
        # get the current frame
        (grabbed, frame) = camera.read()

        # resize the frame
        frame = imutils.resize(frame, width=640)

        # flip the frame so that it is not the mirror view
        frame = cv2.flip(frame, 1)

        # clone the frame
        clone = frame.copy()

        # get the height and width of the frame
        (height, width) = frame.shape[:2]

        # get the ROI
        roi = frame[top:bottom, right:left]

        # convert the roi to grayscale and blur it
        gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (7, 7), 0)

        # to get the background, keep looking till a threshold is reached
        # so that our weighted average model gets calibrated

        if num_frames < 30:
            run_avg(gray, accumWeight)
            if num_frames == 1:
                print("[STATUS] please wait! calibrating...")
            elif num_frames == 29:
                print("[STATUS] calibration successfull...")

        else:
            # segment the hand region
            hand = segment(gray)

            # check whether hand region is segmented
            if hand is not None:
                # if yes, unpack the thresholded image and
                # segmented region
                (thresholded, segmented) = hand


                bbox = calculateBoundImage(thresholded)
                #print(bbox[0],bbox[1],bbox[2],bbox[3])
                bound_thres = 4500
                if bbox[2] > bound_thres or bbox[3] > bound_thres:
                    continue

                #生成ROI图像
                roi_color = frame[10 + bbox[1]:10 + bbox[1] + bbox[3], 380+bbox[0]:380 + bbox[0] + bbox[2]]
                #cv2.imshow("roi_color", roi_color)

                roi_mask = thresholded[bbox[1]:bbox[1] + bbox[3], bbox[0]:bbox[0] + bbox[2]]
                #merged = cv2.merge([b, g, r])
                #cv2.imshow("roi_mask", roi_mask)

                dst = cv2.add(roi_color, np.zeros(np.shape(roi_color), dtype=np.uint8), mask=roi_mask)
                cv2.imshow("dst", dst)

                contour_image = cv2.rectangle(thresholded, (bbox[0], bbox[1]), (bbox[0] + bbox[2], bbox[1] + bbox[3]),
                                              (255), thickness=2)

                # draw the segmented region and display the frame
                cv2.drawContours(clone, [segmented + (right, top)], -1, (0, 0, 255))
                cv2.rectangle(clone, (380 + bbox[0], 10 + bbox[1]),(380 + bbox[0] + bbox[2], 10 + bbox[1] + bbox[3]), (255,0 , 0), 2)

                # count the number of fingers
                #fingers = count(thresholded, segmented)

                #cv2.putText(clone, str(fingers), (70, 45), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
                
                # show the thresholded image
                #cv2.imshow("Thesholded", thresholded)

        # draw the segmented hand
        cv2.rectangle(clone, (left, top), (right, bottom), (0,255,0), 2)


        # increment the number of frames
        num_frames += 1

        # display the frame with segmented hand
        cv2.imshow("Video Feed", clone)

        # observe the keypress by the user
        keypress = cv2.waitKey(1) & 0xFF

        # if the user pressed "q", then stop looping
        if keypress == ord("q"):
            break

# free up memory
camera.release()
cv2.destroyAllWindows()

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值