

{"id":82188,"date":"2020-09-14T18:02:54","date_gmt":"2020-09-14T12:32:54","guid":{"rendered":"https:\/\/data-flair.training\/blogs\/?p=82188"},"modified":"2026-06-01T11:49:04","modified_gmt":"2026-06-01T06:19:04","slug":"sign-language-recognition-python-ml-opencv","status":"publish","type":"post","link":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/","title":{"rendered":"Sign Language Recognition Using Python and OpenCV"},"content":{"rendered":"<p>There have been several advancements in technology and a lot of research has been done to help the people who are deaf and dumb. Aiding the cause, Deep learning, and computer vision can be used too to make an impact on this cause.<\/p>\n<p>This can be very helpful for the deaf and dumb people in communicating with others as knowing sign language is not something that is common to all, moreover, this can be extended to creating automatic editors, where the person can easily write by just their hand gestures.<\/p>\n<h3>Project Overview<\/h3>\n<p>In this sign language recognition project, we create a sign detector, which detects numbers from 1 to 10 that can very easily be extended to cover a vast multitude of other signs and hand gestures including the alphabets.<\/p>\n<p>We have developed this project using OpenCV and Keras modules of python.<\/p>\n<h3>Prerequisites<\/h3>\n<p>The prerequisites software &amp; libraries for the sign language project are:<\/p>\n<ul>\n<li>Python (3.7.4)<\/li>\n<li>IDE (Jupyter)<\/li>\n<li>Numpy (version 1.16.5)<\/li>\n<li>cv2 (openCV) (version 3.4.2)<\/li>\n<li>Keras (version 2.3.1)<\/li>\n<li>Tensorflow (as keras uses tensorflow in backend and for image preprocessing) (version 2.0.0)<\/li>\n<\/ul>\n<h3>Download Sign Language Project Code<\/h3>\n<p>Please download the source code of sign language machine learning project: <a href=\"https:\/\/drive.google.com\/file\/d\/1Nh7S5ABDU_1R47w2BlKmkuQStZdSX8_9\/view?usp=drive_link\"><strong>Sign Language Recognition Project<\/strong><\/a><\/p>\n<h3>Steps to develop sign language recognition project<\/h3>\n<p>This is divided into 3 parts:<\/p>\n<ol>\n<li>Creating the dataset<\/li>\n<li>Training a CNN on the captured dataset<\/li>\n<li>Predicting the data<\/li>\n<\/ol>\n<p>All of which are created as three separate .py files.\u00a0The file structure is given below:<\/p>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/file-structure.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82210\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/file-structure.png\" alt=\"project file structure\" width=\"1020\" height=\"440\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/file-structure.png 1020w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/file-structure-300x129.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/file-structure-150x65.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/file-structure-768x331.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/file-structure-520x224.png 520w\" sizes=\"auto, (max-width: 1020px) 100vw, 1020px\" \/><\/a><\/p>\n<h3>1. Creating the dataset for sign language detection:<\/h3>\n<p>It is fairly possible to get the dataset we need on the internet but in this project, we will be creating the dataset on our own.<\/p>\n<p>We will be having a live feed from the video cam and every frame that detects a hand in the ROI (region of interest) created will be saved in a directory (here gesture directory) that contains two folders train and test, each containing 10 folders containing images captured using the create_gesture_data.py<\/p>\n<p><strong>Directory structure<\/strong><\/p>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/directory-structure.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82213\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/directory-structure.png\" alt=\"directory structure\" width=\"1020\" height=\"440\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/directory-structure.png 1020w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/directory-structure-300x129.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/directory-structure-150x65.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/directory-structure-768x331.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/directory-structure-520x224.png 520w\" sizes=\"auto, (max-width: 1020px) 100vw, 1020px\" \/><\/a><\/p>\n<p><strong>Inside of train (test has the same structure inside)<\/strong><\/p>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82214\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training.png\" alt=\"training\" width=\"1020\" height=\"444\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training.png 1020w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-300x131.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-150x65.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-768x334.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-520x226.png 520w\" sizes=\"auto, (max-width: 1020px) 100vw, 1020px\" \/><\/a><\/p>\n<p>Now for creating the dataset we get the live cam feed using OpenCV and create an ROI that is nothing but the part of the frame where we want to detect the hand in for the gestures.<\/p>\n<p>The red box is the ROI and this window is for getting the live cam feed from the webcam.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82243\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame.png\" alt=\"create roi\" width=\"1899\" height=\"911\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame.png 1899w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame-300x144.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame-1024x491.png 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame-150x72.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame-768x368.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame-1536x737.png 1536w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/create-roi-frame-520x249.png 520w\" sizes=\"auto, (max-width: 1899px) 100vw, 1899px\" \/><\/a><\/p>\n<p>For differentiating between the background we calculate the accumulated weighted avg for the background and then subtract this from the frames that contain some object in front of the background that can be distinguished as foreground.<\/p>\n<p>This is done by calculating the accumulated_weight for some frames (here for 60 frames) we calculate the accumulated_avg for the background.<\/p>\n<p>After we have the accumulated avg for the background, we subtract it from every frame that we read after 60 frames to find any object that covers the background.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">import tensorflow as tf\r\nfrom tensorflow import keras\r\nfrom keras.models import Sequential\r\nfrom keras.layers import Activation, Dense, Flatten, BatchNormalization, Conv2D, MaxPool2D, Dropout\r\nfrom keras.optimizers import Adam, SGD\r\nfrom keras.metrics import categorical_crossentropy\r\nfrom keras.preprocessing.image import ImageDataGenerator\r\n\r\nimport warnings\r\nimport numpy as np\r\nimport cv2\r\nfrom keras.callbacks import ReduceLROnPlateau\r\nfrom keras.callbacks import ModelCheckpoint, EarlyStopping\r\nwarnings.simplefilter(action='ignore', category=FutureWarning)\r\n\r\n\r\nbackground = None\r\naccumulated_weight = 0.5\r\n\r\n#Creating the dimensions for the ROI...\r\nROI_top = 100\r\nROI_bottom = 300\r\nROI_right = 150\r\nROI_left = 350\r\n\r\n\r\ndef cal_accum_avg(frame, accumulated_weight):\r\n\r\n    global background\r\n    \r\n    if background is None:\r\n        background = frame.copy().astype(\"float\")\r\n        return None\r\n\r\n    cv2.accumulateWeighted(frame, background, accumulated_weight)\r\n<\/pre>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82244\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background.png\" alt=\"fetch background\" width=\"1887\" height=\"900\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background.png 1887w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background-300x143.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background-1024x488.png 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background-150x72.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background-768x366.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background-1536x733.png 1536w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/fetch-background-520x248.png 520w\" sizes=\"auto, (max-width: 1887px) 100vw, 1887px\" \/><\/a><\/p>\n<p>(We put up a text using cv2.putText to display to wait and not put any object or hand in the ROI while detecting the background)<\/p>\n<h4>Calculate threshold value<\/h4>\n<p>Now we calculate the threshold value for every frame and determine the contours using cv2.findContours and return the max contours (the most outermost contours for the object) using the function segment. Using the contours we are able to determine if there is any foreground object being detected in the ROI, in other words, if there is a hand in the ROI.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">def segment_hand(frame, threshold=25):\r\n    global background\r\n    \r\n    diff = cv2.absdiff(background.astype(\"uint8\"), frame)\r\n\r\n    _ , thresholded = cv2.threshold(diff, threshold,255,cv2.THRESH_BINARY)\r\n\r\n    # Grab the external contours for the image\r\n    image, contours, hierarchy = cv2.findContours(thresholded.copy(),\r\n    cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n\r\n    if len(contours) == 0:\r\n        return None\r\n    else:\r\n        \r\n        hand_segment_max_cont = max(contours, key=cv2.contourArea)\r\n        \r\n        return (thresholded, hand_segment_max_cont)\r\n<\/pre>\n<p>When contours are detected (or hand is present in the ROI), We start to save the image of the ROI in the train and test set respectively for the letter or number we are detecting it for.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">cam = cv2.VideoCapture(0)\r\n\r\nnum_frames = 0\r\nelement = 10\r\nnum_imgs_taken = 0\r\n\r\nwhile True:\r\n    ret, frame = cam.read()\r\n\r\n    # flipping the frame to prevent inverted image of captured frame...\r\n    frame = cv2.flip(frame, 1)\r\n\r\n    frame_copy = frame.copy()\r\n\r\n    roi = frame[ROI_top:ROI_bottom, ROI_right:ROI_left]\r\n\r\n    gray_frame = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)\r\n    gray_frame = cv2.GaussianBlur(gray_frame, (9, 9), 0)\r\n\r\n    if num_frames &lt; 60:\r\n        cal_accum_avg(gray_frame, accumulated_weight)\r\n        if num_frames &lt;= 59:\r\n            \r\n            cv2.putText(frame_copy, \"FETCHING BACKGROUND...PLEASE WAIT\",\r\n(80, 400), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,0,255), 2)\r\n            \r\n    #Time to configure the hand specifically into the ROI...\r\n    elif num_frames &lt;= 300: \r\n\r\n        hand = segment_hand(gray_frame)\r\n        \r\n        cv2.putText(frame_copy, \"Adjust hand...Gesture for\" +\r\n  str(element), (200, 400), cv2.FONT_HERSHEY_SIMPLEX, 1,\r\n  (0,0,255),2)\r\n        \r\n        # Checking if the hand is actually detected by counting the number\r\n        of contours detected...\r\n        if hand is not None:\r\n            \r\n            thresholded, hand_segment = hand\r\n\r\n            # Draw contours around hand segment\r\n            cv2.drawContours(frame_copy, [hand_segment + (ROI_right,\r\n            ROI_top)], -1, (255, 0, 0),1)\r\n            \r\n            cv2.putText(frame_copy, str(num_frames)+\"For\" + str(element),\r\n            (70, 45), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)\r\n\r\n            # Also display the thresholded image\r\n            cv2.imshow(\"Thresholded Hand Image\", thresholded)\r\n    \r\n    else: \r\n        \r\n        # Segmenting the hand region...\r\n        hand = segment_hand(gray_frame)\r\n        \r\n        # Checking if we are able to detect the hand...\r\n        if hand is not None:\r\n            \r\n            # unpack the thresholded img and the max_contour...\r\n            thresholded, hand_segment = hand\r\n\r\n            # Drawing contours around hand segment\r\n            cv2.drawContours(frame_copy, [hand_segment + (ROI_right,\r\n            ROI_top)], -1, (255, 0, 0),1)\r\n            \r\n            cv2.putText(frame_copy, str(num_frames), (70, 45),\r\n            cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)\r\n            \r\n            cv2.putText(frame_copy, str(num_imgs_taken) + 'images' +\"For\"\r\n      + str(element), (200, 400), cv2.FONT_HERSHEY_SIMPLEX, 1,\r\n      (0,0,255), 2)\r\n            \r\n            # Displaying the thresholded image\r\n            cv2.imshow(\"Thresholded Hand Image\", thresholded)\r\n            if num_imgs_taken &lt;= 300:\r\n                cv2.imwrite(r\"D:\\\\gesture\\\\train\\\\\"+str(element)+\"\\\\\" +\r\n                str(num_imgs_taken+300) + '.jpg', thresholded)\r\n                \r\n            else:\r\n                break\r\n            num_imgs_taken +=1\r\n        else:\r\n            cv2.putText(frame_copy, 'No hand detected...', (200, 400),\r\n cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)\r\n\r\n\r\n\r\n\r\n    # Drawing ROI on frame copy\r\n    cv2.rectangle(frame_copy, (ROI_left, ROI_top), (ROI_right,ROI_bottom), (255,128,0), 3)\r\n    \r\n    cv2.putText(frame_copy, \"DataFlair hand sign recognition_ _ _\", (10, 20), cv2.FONT_ITALIC, 0.5, (51,255,51), 1)\r\n    \r\n    # increment the number of frames for tracking\r\n    num_frames += 1\r\n\r\n    # Display the frame with segmented hand\r\n    cv2.imshow(\"Sign Detection\", frame_copy)\r\n\r\n    # Closing windows with Esc key...(any other key with ord can be used too.)\r\n    k = cv2.waitKey(1) &amp; 0xFF\r\n\r\n    if k == 27:\r\n        break\r\n\r\n# Releasing the camera &amp; destroying all the windows...\r\n\r\ncv2.destroyAllWindows()\r\ncam.release()\r\n<\/pre>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82216\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1.png\" alt=\"dataset generation\" width=\"1920\" height=\"1033\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1.png 1920w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1-300x161.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1-1024x551.png 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1-150x81.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1-768x413.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1-1536x826.png 1536w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/dataset-gen-1-520x280.png 520w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/a><\/p>\n<p>In the above example, the dataset for 1 is being created and the thresholded image of the ROI is being shown in the next window and this frame of ROI is being saved in ..train\/1\/example.jpg<\/p>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82217\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset.png\" alt=\"training dataset\" width=\"1676\" height=\"964\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset.png 1676w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset-300x173.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset-1024x589.png 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset-150x86.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset-768x442.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset-1536x883.png 1536w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/training-dataset-520x299.png 520w\" sizes=\"auto, (max-width: 1676px) 100vw, 1676px\" \/><\/a><\/p>\n<p>For the train dataset, we save 701 images for each number to be detected, and for the test dataset, we do the same and create 40 images for each number.<\/p>\n<h3>2. Training CNN<\/h3>\n<p>Now on the created data set we train a CNN.<\/p>\n<p>First, we load the data using ImageDataGenerator of keras through which we can use the flow_from_directory function to load the train and test set data, and each of the names of the number folders will be the class names for the imgs loaded.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">train_path = r'D:\\gesture\\train'\r\ntest_path = r'D:\\gesture\\test'\r\n\r\ntrain_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=train_path, target_size=(64,64), class_mode='categorical', batch_size=10,shuffle=True)\r\ntest_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=test_path, target_size=(64,64), class_mode='categorical', batch_size=10, shuffle=True)\r\n<\/pre>\n<p>plotImages function is for plotting images of the dataset loaded.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">imgs, labels = next(train_batches)\r\n\r\n#Plotting the images...\r\ndef plotImages(images_arr):\r\n    fig, axes = plt.subplots(1, 10, figsize=(30,20))\r\n    axes = axes.flatten()\r\n    for img, ax in zip( images_arr, axes):\r\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\r\n        ax.imshow(img)\r\n        ax.axis('off')\r\n    plt.tight_layout()\r\n    plt.show()\r\n\r\n\r\nplotImages(imgs)\r\nprint(imgs.shape)\r\nprint(labels)\r\n<\/pre>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82219\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function.png\" alt=\"plotimages function\" width=\"1920\" height=\"1033\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function.png 1920w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function-300x161.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function-1024x551.png 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function-150x81.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function-768x413.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function-1536x826.png 1536w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/plotimages-function-520x280.png 520w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/a><\/p>\n<p>Now we design the CNN as follows (or depending upon some trial and error other hyperparameters can be used)<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">model = Sequential()\r\n\r\nmodel.add(Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(64,64,3)))\r\nmodel.add(MaxPool2D(pool_size=(2, 2), strides=2))\r\n\r\nmodel.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding = 'same'))\r\nmodel.add(MaxPool2D(pool_size=(2, 2), strides=2))\r\n\r\nmodel.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu', padding = 'valid'))\r\nmodel.add(MaxPool2D(pool_size=(2, 2), strides=2))\r\n\r\nmodel.add(Flatten())\r\n\r\nmodel.add(Dense(64,activation =\"relu\"))\r\nmodel.add(Dense(128,activation =\"relu\"))\r\n#model.add(Dropout(0.2))\r\nmodel.add(Dense(128,activation =\"relu\"))\r\n#model.add(Dropout(0.3))\r\nmodel.add(Dense(10,activation =\"softmax\"))\r\n\r\n<\/pre>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82220\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model.png\" alt=\"model\" width=\"1920\" height=\"1033\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model.png 1920w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-300x161.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-1024x551.png 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-150x81.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-768x413.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-1536x826.png 1536w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-520x280.png 520w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/a><\/p>\n<p>Now we fit the model and save the model for it to be used in the last module (model_for_gesture.py)<\/p>\n<p>In training callbacks of Reduce LR on plateau and earlystopping is used, and both of them are dependent on the validation dataset loss.<\/p>\n<p>After every epoch, the accuracy and loss are calculated using the validation dataset and if the validation loss is not decreasing, the LR of the model is reduced using the Reduce LR to prevent the model from overshooting the minima of loss and also we are using the earlystopping algorithm so that if the validation accuracy keeps on decreasing for some epochs then the training is stopped.<\/p>\n<p>The example contains the callbacks used, also it contains the two different optimization algorithms used &#8211; SGD (stochastic gradient descent, that means the weights are updated at every training instance) and Adam (combination of Adagrad and RMSProp) is used.<\/p>\n<p>We found for the model SGD seemed to give higher accuracies. As we can see while training we found 100% training accuracy and validation accuracy of about 81%<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">model.compile(optimizer=Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])\r\nreduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=1, min_lr=0.0001)\r\nearly_stop = EarlyStopping(monitor='val_loss', min_delta=0, patience=2, verbose=0, mode='auto')\r\n\r\n\r\n\r\nmodel.compile(optimizer=SGD(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])\r\nreduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=1, min_lr=0.0005)\r\nearly_stop = EarlyStopping(monitor='val_loss', min_delta=0, patience=2, verbose=0, mode='auto')\r\n<\/pre>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82221\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile.png\" alt=\"model compile\" width=\"1920\" height=\"1033\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile.png 1920w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile-300x161.png 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile-1024x551.png 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile-150x81.png 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile-768x413.png 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile-1536x826.png 1536w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/model-compile-520x280.png 520w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/a><\/p>\n<p>After compiling the model we fit the model on the train batches for 10 epochs (may vary according to the choice of parameters of the user), using the callbacks discussed above.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">history2 = model.fit(train_batches, epochs=10, callbacks=[reduce_lr, early_stop],  validation_data = test_batches)\r\n<\/pre>\n<p>We are now getting the next batch of images from the test data &amp; evaluating the model on the test set and printing the accuracy and loss scores.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\"># For getting next batch of testing imgs...\r\nimgs, labels = next(test_batches) \r\n\r\nscores = model.evaluate(imgs, labels, verbose=0)\r\nprint(f'{model.metrics_names[0]} of {scores[0]}; {model.metrics_names[1]} of {scores[1]*100}%')\r\n\r\n\r\nOnce the model is fitted we save the model using model.save()  function.\r\n\r\n\r\nmodel.save('best_model_dataflair3.h5')\r\n<\/pre>\n<p>Here we are visualizing and making a small test on the model to check if everything is working as we expect it to while detecting on the live cam feed.<\/p>\n<p>The word_dict is the dictionary containing label names for the various labels predicted.<\/p>\n<p>(Note: Here in the dictionary we have \u2018Ten\u2019 after \u2018One\u2019, the reason being that while loading the dataset using the ImageDataGenerator, the generator considers the folders inside of the test and train folders on the basis of their folder names, ex: &#8216;1&#8217;, &#8217;10&#8217;. Due to this 10 comes after 1 in alphabetical order).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">word_dict = {0:'One',1:'Ten',2:'Two',3:'Three',4:'Four',5:'Five',6:'Six',7:'Seven',8:'Eight',9:'Nine'}\r\n\r\npredictions = model.predict(imgs, verbose=0)\r\nprint(\"predictions on a small set of test data--\")\r\nprint(\"\")\r\nfor ind, i in enumerate(predictions):\r\n    print(word_dict[np.argmax(i)], end='   ')\r\n\r\nplotImages(imgs)\r\nprint('Actual labels')\r\nfor i in labels:\r\n    print(word_dict[np.argmax(i)], end='   ')\r\n<\/pre>\n<h3>3. Predict the gesture<\/h3>\n<p>In this, we create a bounding box for detecting the ROI and calculate the accumulated_avg as we did in creating the dataset. This is done for identifying any foreground object.<\/p>\n<p>Now we find the max contour and if contour is detected that means a hand is detected so the threshold of the ROI is treated as a test image.<\/p>\n<p>We load the previously saved model using keras.models.load_model and feed the threshold image of the ROI consisting of the hand as an input to the model for prediction.<\/p>\n<p>Getting the necessary imports for model_for_gesture.py<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">import numpy as np\r\nimport cv2\r\nimport keras\r\nfrom keras.preprocessing.image import ImageDataGenerator\r\nimport tensorflow as tf\r\n<\/pre>\n<p>Now we load the model that we had created earlier and set some of the variables that we need, i.e, initializing the background variable, and setting the dimensions of the ROI.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">model = keras.models.load_model(r\"C:\\Users\\abhij\\best_model_dataflair3.h5\")\r\n\r\nbackground = None\r\naccumulated_weight = 0.5\r\n\r\nROI_top = 100\r\nROI_bottom = 300\r\nROI_right = 150\r\nROI_left = 350\r\n<\/pre>\n<p>Function to calculate the background accumulated weighted average (like we did while creating the dataset&#8230;)<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">def cal_accum_avg(frame, accumulated_weight):\r\n\r\n    global background\r\n    \r\n    if background is None:\r\n        background = frame.copy().astype(\"float\")\r\n        return None\r\n\r\n    cv2.accumulateWeighted(frame, background, accumulated_weight)\r\n<\/pre>\n<p>Segmenting the hand, i.e, getting the max contours and the thresholded image of the hand detected.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">def segment_hand(frame, threshold=25):\r\n    global background\r\n    \r\n    diff = cv2.absdiff(background.astype(\"uint8\"), frame)\r\n\r\n    \r\n_ , thresholded = cv2.threshold(diff, threshold, 255,\r\ncv2.THRESH_BINARY)\r\n    \r\n     #Fetching contours in the frame (These contours can be of hand\r\nor any other object in foreground) \u2026\r\n\r\n    image, contours, hierarchy =\r\n    cv2.findContours(thresholded.copy(), cv2.RETR_EXTERNAL,\r\n    cv2.CHAIN_APPROX_SIMPLE)\r\n\r\n    # If length of contours list = 0, means we didn't get any\r\n    contours...\r\n    if len(contours) == 0:\r\n        return None\r\n    else:\r\n        # The largest external contour should be the hand \r\n        hand_segment_max_cont = max(contours, key=cv2.contourArea)\r\n        \r\n        # Returning the hand segment(max contour) and the\r\n  thresholded image of hand...\r\n        return (thresholded, hand_segment_max_cont)\r\n<\/pre>\n<p>Detecting the hand now on the live cam feed.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">cam = cv2.VideoCapture(0)\r\nnum_frames =0\r\nwhile True:\r\n    ret, frame = cam.read()\r\n\r\n    # flipping the frame to prevent inverted image of captured\r\n    frame...\r\n    \r\n    frame = cv2.flip(frame, 1)\r\n\r\n    frame_copy = frame.copy()\r\n\r\n    # ROI from the frame\r\n    roi = frame[ROI_top:ROI_bottom, ROI_right:ROI_left]\r\n\r\n    gray_frame = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)\r\n    gray_frame = cv2.GaussianBlur(gray_frame, (9, 9), 0)\r\n\r\n\r\n    if num_frames &lt; 70:\r\n        \r\n        cal_accum_avg(gray_frame, accumulated_weight)\r\n        \r\n        cv2.putText(frame_copy, \"FETCHING BACKGROUND...PLEASE WAIT\",\r\n  (80, 400), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,0,255), 2)\r\n    \r\n    else: \r\n        # segmenting the hand region\r\n        hand = segment_hand(gray_frame)\r\n        \r\n        # Checking if we are able to detect the hand...\r\n        if hand is not None:\r\n            \r\n            thresholded, hand_segment = hand\r\n\r\n            # Drawing contours around hand segment\r\n            cv2.drawContours(frame_copy, [hand_segment + (ROI_right,\r\n      ROI_top)], -1, (255, 0, 0),1)\r\n            \r\n            cv2.imshow(\"Thesholded Hand Image\", thresholded)\r\n            \r\n            thresholded = cv2.resize(thresholded, (64, 64))\r\n            thresholded = cv2.cvtColor(thresholded,\r\n cv2.COLOR_GRAY2RGB)\r\n            thresholded = np.reshape(thresholded,\r\n(1,thresholded.shape[0],thresholded.shape[1],3))\r\n            \r\n            pred = model.predict(thresholded)\r\n            cv2.putText(frame_copy, word_dict[np.argmax(pred)],\r\n(170, 45), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)\r\n            \r\n    # Draw ROI on frame_copy\r\n    cv2.rectangle(frame_copy, (ROI_left, ROI_top), (ROI_right,\r\n    ROI_bottom), (255,128,0), 3)\r\n\r\n    # incrementing the number of frames for tracking\r\n    num_frames += 1\r\n\r\n    # Display the frame with segmented hand\r\n    cv2.putText(frame_copy, \"DataFlair hand sign recognition_ _ _\",\r\n    (10, 20), cv2.FONT_ITALIC, 0.5, (51,255,51), 1)\r\n    cv2.imshow(\"Sign Detection\", frame_copy)\r\n\r\n\r\n    # Close windows with Esc\r\n    k = cv2.waitKey(1) &amp; 0xFF\r\n\r\n    if k == 27:\r\n        break\r\n\r\n# Release the camera and destroy all the windows\r\ncam.release()\r\ncv2.destroyAllWindows()\r\n<\/pre>\n<h3>Sign Language Recognition Output<\/h3>\n<p><a href=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-82222\" src=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output.jpg\" alt=\"sign language recognition output\" width=\"1059\" height=\"451\" srcset=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output.jpg 1059w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output-300x128.jpg 300w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output-1024x436.jpg 1024w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output-150x64.jpg 150w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output-768x327.jpg 768w, https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-output-520x221.jpg 520w\" sizes=\"auto, (max-width: 1059px) 100vw, 1059px\" \/><\/a><\/p>\n<h3>Summary<\/h3>\n<p>Sign language helps people who cannot speak. This project uses machine learning and computer vision to recognize hand gestures and convert them into text or speech. Using OpenCV and Python, we build a system that can understand simple sign language like A\u2013Z or numbers.<\/p>\n<p>We have successfully developed sign language detection project. This is an interesting machine learning python project to gain expertise. This can be further extended for detecting the English alphabets.<\/p>\n<p>This project is helpful for the disabled and builds awareness about assistive technology. It teaches data collection, gesture recognition, CNN, and OpenCV. It\u2019s an amazing real-world project with social impact.<span hidden class=\"__iawmlf-post-loop-links\" data-iawmlf-links=\"[{&quot;id&quot;:2495,&quot;href&quot;:&quot;https:\\\/\\\/drive.google.com\\\/file\\\/d\\\/1Nh7S5ABDU_1R47w2BlKmkuQStZdSX8_9\\\/view?usp=drive_link&quot;,&quot;archived_href&quot;:&quot;http:\\\/\\\/web-wp.archive.org\\\/web\\\/20260601062010\\\/https:\\\/\\\/drive.google.com\\\/file\\\/d\\\/1Nh7S5ABDU_1R47w2BlKmkuQStZdSX8_9\\\/view?usp=drive_link&quot;,&quot;redirect_href&quot;:&quot;&quot;,&quot;checks&quot;:[{&quot;date&quot;:&quot;2026-06-01 07:22:44&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-04 08:12:34&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-07 12:02:51&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-10 13:03:27&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-13 14:43:11&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-16 19:11:50&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-19 19:46:32&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-23 04:23:25&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-26 06:34:34&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-06-29 09:21:36&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-02 10:51:57&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-05 11:21:02&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-08 11:49:30&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-12 04:49:12&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-15 06:55:40&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-18 08:44:00&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-21 11:55:45&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-24 18:30:08&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-07-28 04:57:18&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-02 04:01:01&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-05 07:18:43&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-08 07:44:09&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-11 10:14:19&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-14 11:22:35&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-17 15:34:47&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-20 16:04:43&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-23 19:21:16&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-26 19:39:55&quot;,&quot;http_code&quot;:200},{&quot;date&quot;:&quot;2026-08-30 12:53:06&quot;,&quot;http_code&quot;:200}],&quot;broken&quot;:false,&quot;last_checked&quot;:{&quot;date&quot;:&quot;2026-08-30 12:53:06&quot;,&quot;http_code&quot;:200},&quot;process&quot;:&quot;done&quot;}]\"><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>There have been several advancements in technology and a lot of research has been done to help the people who are deaf and dumb. Aiding the cause, Deep learning, and computer vision can be&#46;&#46;&#46;<\/p>\n","protected":false},"author":5,"featured_media":82223,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36],"tags":[34992,34993,34991],"class_list":["post-82188","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-machine-learning","tag-opencv-easy-project","tag-opencv-project-for-beginners","tag-sign-language-recognition-project"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Sign Language Recognition Using Python and OpenCV - DataFlair<\/title>\n<meta name=\"description\" content=\"Sign language recognition project with Python, CNN &amp; OpenCV - Detect sign language and help dumb and deaf people in communicating with others\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Sign Language Recognition Using Python and OpenCV - DataFlair\" \/>\n<meta property=\"og:description\" content=\"Sign language recognition project with Python, CNN &amp; OpenCV - Detect sign language and help dumb and deaf people in communicating with others\" \/>\n<meta property=\"og:url\" content=\"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/\" \/>\n<meta property=\"og:site_name\" content=\"DataFlair\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/DataFlairWS\/\" \/>\n<meta property=\"article:published_time\" content=\"2020-09-14T12:32:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-01T06:19:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-python-opencv.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"DataFlair Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@DataFlairWS\" \/>\n<meta name=\"twitter:site\" content=\"@DataFlairWS\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"DataFlair Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Sign Language Recognition Using Python and OpenCV - DataFlair","description":"Sign language recognition project with Python, CNN & OpenCV - Detect sign language and help dumb and deaf people in communicating with others","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/","og_locale":"en_US","og_type":"article","og_title":"Sign Language Recognition Using Python and OpenCV - DataFlair","og_description":"Sign language recognition project with Python, CNN & OpenCV - Detect sign language and help dumb and deaf people in communicating with others","og_url":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/","og_site_name":"DataFlair","article_publisher":"https:\/\/www.facebook.com\/DataFlairWS\/","article_published_time":"2020-09-14T12:32:54+00:00","article_modified_time":"2026-06-01T06:19:04+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-python-opencv.jpg","type":"image\/jpeg"}],"author":"DataFlair Team","twitter_card":"summary_large_image","twitter_creator":"@DataFlairWS","twitter_site":"@DataFlairWS","twitter_misc":{"Written by":"DataFlair Team","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#article","isPartOf":{"@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/"},"author":{"name":"DataFlair Team","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/person\/7f83c342f5d1632d6f7b4b0b0f447823"},"headline":"Sign Language Recognition Using Python and OpenCV","datePublished":"2020-09-14T12:32:54+00:00","dateModified":"2026-06-01T06:19:04+00:00","mainEntityOfPage":{"@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/"},"wordCount":1374,"commentCount":131,"publisher":{"@id":"https:\/\/data-flair.training\/blogs\/#organization"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#primaryimage"},"thumbnailUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-python-opencv.jpg","keywords":["opencv easy project","opencv project for beginners","sign language recognition project"],"articleSection":["Machine Learning Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/","url":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/","name":"Sign Language Recognition Using Python and OpenCV - DataFlair","isPartOf":{"@id":"https:\/\/data-flair.training\/blogs\/#website"},"primaryImageOfPage":{"@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#primaryimage"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#primaryimage"},"thumbnailUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-python-opencv.jpg","datePublished":"2020-09-14T12:32:54+00:00","dateModified":"2026-06-01T06:19:04+00:00","description":"Sign language recognition project with Python, CNN & OpenCV - Detect sign language and help dumb and deaf people in communicating with others","breadcrumb":{"@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#primaryimage","url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-python-opencv.jpg","contentUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2020\/09\/sign-language-recognition-python-opencv.jpg","width":1200,"height":628,"caption":"sign language recognition python opencv"},{"@type":"BreadcrumbList","@id":"https:\/\/data-flair.training\/blogs\/sign-language-recognition-python-ml-opencv\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Blog Home","item":"https:\/\/data-flair.training\/blogs\/"},{"@type":"ListItem","position":2,"name":"Machine Learning Tutorials","item":"https:\/\/data-flair.training\/blogs\/category\/machine-learning\/"},{"@type":"ListItem","position":3,"name":"Sign Language Recognition Using Python and OpenCV"}]},{"@type":"WebSite","@id":"https:\/\/data-flair.training\/blogs\/#website","url":"https:\/\/data-flair.training\/blogs\/","name":"DataFlair","description":"Learn Today. Lead Tomorrow.","publisher":{"@id":"https:\/\/data-flair.training\/blogs\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/data-flair.training\/blogs\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/data-flair.training\/blogs\/#organization","name":"DataFlair","url":"https:\/\/data-flair.training\/blogs\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/logo\/image\/","url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2016\/07\/Data-Flair.png","contentUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2016\/07\/Data-Flair.png","width":106,"height":48,"caption":"DataFlair"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/DataFlairWS\/","https:\/\/x.com\/DataFlairWS","https:\/\/www.linkedin.com\/company\/dataflair-web-services-pvt-ltd\/","https:\/\/www.youtube.com\/user\/DataFlairWS"]},{"@type":"Person","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/person\/7f83c342f5d1632d6f7b4b0b0f447823","name":"DataFlair Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4cf3a74600d131330b8c481d519afd1574093ed89f6d3396a95393ad223eb7cd?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4cf3a74600d131330b8c481d519afd1574093ed89f6d3396a95393ad223eb7cd?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4cf3a74600d131330b8c481d519afd1574093ed89f6d3396a95393ad223eb7cd?s=96&d=mm&r=g","caption":"DataFlair Team"},"description":"DataFlair Team creates expert-level guides on programming, Java, Python, C++, DSA, AI, ML, data Science, Android, Flutter, MERN, Web Development, and technology. Our goal is to empower learners with easy-to-understand content. Explore our resources for career growth and practical learning.","url":"https:\/\/data-flair.training\/blogs\/author\/dfteam1\/"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/82188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/comments?post=82188"}],"version-history":[{"count":10,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/82188\/revisions"}],"predecessor-version":[{"id":148563,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/82188\/revisions\/148563"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/media\/82223"}],"wp:attachment":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/media?parent=82188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/categories?post=82188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/tags?post=82188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}