github-open-source-code-for-hand-gesture-recognition-?-sign-language-translation

This doc focuses on the
example graph
that performs hand tracking with TensorFlow Lite on GPU. It is related to the
hand detection example, and we recommend users
to review the hand detection example first.

For overall context on hand detection and hand tracking, please read this
Google AI Blog post.

hand_tracking_android_gpu.gif

In the visualization above, the red dots represent the localized hand landmarks,
and the green lines are simply connections between selected landmark pairs for
visualization of the hand skeleton. The red box represents a hand rectangle that
covers the entire hand, derived either from hand detection (see
hand detection example) or from the pervious
round of hand landmark localization using an ML model (see also
model card). Hand landmark localization is
performed only within the hand rectangle for computational efficiency and
accuracy, and hand detection is only invoked when landmark localization could
not identify hand presence in the previous iteration.

The example can also run in a mode that localizes hand landmarks in 3D (i.e.,
estimating an extra z coordinate):

hand_tracking_3d_android_gpu.gif

In the visualization above, the localized hand landmarks are represented by dots
in different shades, with the brighter ones denoting landmarks closer to the
camera.

Android

Source

An arm64 APK can be
downloaded here,
and a version running the 3D mode can be
downloaded here.

To build the app yourself, run:

bazel build -c opt --config=android_arm64 mediapipe/examples/android/src/java/com/google/mediapipe/apps/handtrackinggpu

To build for the 3D mode, run:

bazel build -c opt --config=android_arm64 --define 3D=true mediapipe/examples/android/src/java/com/google/mediapipe/apps/handtrackinggpu

Once the app is built, install it on Android device with:

adb install bazel-bin/mediapipe/examples/android/src/java/com/google/mediapipe/apps/handtrackinggpu/handtrackinggpu.apk

iOS

Source.

See the general instructions for building iOS
examples and generating an Xcode project. This will be the HandDetectionGpuApp
target.

To build on the command line:

bazel build -c opt --config=ios_arm64 mediapipe/examples/ios/handtrackinggpu:HandTrackingGpuApp

To build for the 3D mode, run:

bazel build -c opt --config=ios_arm64 --define 3D=true mediapipe/examples/ios/handtrackinggpu:HandTrackingGpuApp

Graph

The hand tracking main graph internally utilizes a
hand detection subgraph, a
hand landmark subgraph and a
renderer subgraph.

The subgraphs show up in the main graph visualization as nodes colored in
purple, and the subgraph itself can also be visualized just like a regular
graph. For more information on how to visualize a graph that includes subgraphs,
see the Visualizing Subgraphs section in the
visualizer documentation.

Main Graph

hand_tracking_mobile_graph

Source pbtxt file

# MediaPipe graph that performs hand tracking with TensorFlow Lite on GPU.
# Used in the examples in
# mediapipie/examples/android/src/java/com/mediapipe/apps/handtrackinggpu and
# mediapipie/examples/ios/handtrackinggpu.

# Images coming into and out of the graph.
input_stream: "input_video"
output_stream: "output_video"

# Throttles the images flowing downstream for flow control. It passes through
# the very first incoming image unaltered, and waits for downstream nodes
# (calculators and subgraphs) in the graph to finish their tasks before it
# passes through another image. All images that come in while waiting are
# dropped, limiting the number of in-flight images in most part of the graph to
# 1. This prevents the downstream nodes from queuing up incoming images and data
# excessively, which leads to increased latency and memory usage, unwanted in
# real-time mobile applications. It also eliminates unnecessarily computation,
# e.g., the output produced by a node may get dropped downstream if the
# subsequent nodes are still busy processing previous inputs.
node {
  calculator: "FlowLimiterCalculator"
  input_stream: "input_video"
  input_stream: "FINISHED:hand_rect"
  input_stream_info: {
    tag_index: "FINISHED"
    back_edge: true
  }
  output_stream: "throttled_input_video"
}

# Caches a hand-presence decision fed back from HandLandmarkSubgraph, and upon
# the arrival of the next input image sends out the cached decision with the
# timestamp replaced by that of the input image, essentially generating a packet
# that carries the previous hand-presence decision. Note that upon the arrival
# of the very first input image, an empty packet is sent out to jump start the
# feedback loop.
node {
  calculator: "PreviousLoopbackCalculator"
  input_stream: "MAIN:throttled_input_video"
  input_stream: "LOOP:hand_presence"
  input_stream_info: {
    tag_index: "LOOP"
    back_edge: true
  }
  output_stream: "PREV_LOOP:prev_hand_presence"
}

# Drops the incoming image if HandLandmarkSubgraph was able to identify hand
# presence in the previous image. Otherwise, passes the incoming image through
# to trigger a new round of hand detection in HandDetectionSubgraph.
node {
  calculator: "GateCalculator"
  input_stream: "throttled_input_video"
  input_stream: "DISALLOW:prev_hand_presence"
  output_stream: "hand_detection_input_video"

  node_options: {
    [type.googleapis.com/mediapipe.GateCalculatorOptions] {
      empty_packets_as_allow: true
    }
  }
}

# Subgraph that detections hands (see hand_detection_gpu.pbtxt).
node {
  calculator: "HandDetectionSubgraph"
  input_stream: "hand_detection_input_video"
  output_stream: "DETECTIONS:palm_detections"
  output_stream: "NORM_RECT:hand_rect_from_palm_detections"
}

# Subgraph that localizes hand landmarks (see hand_landmark_gpu.pbtxt).
node {
  calculator: "HandLandmarkSubgraph"
  input_stream: "IMAGE:throttled_input_video"
  input_stream: "NORM_RECT:hand_rect"
  output_stream: "LANDMARKS:hand_landmarks"
  output_stream: "NORM_RECT:hand_rect_from_landmarks"
  output_stream: "PRESENCE:hand_presence"
}

# Caches a hand rectangle fed back from HandLandmarkSubgraph, and upon the
# arrival of the next input image sends out the cached rectangle with the
# timestamp replaced by that of the input image, essentially generating a packet
# that carries the previous hand rectangle. Note that upon the arrival of the
# very first input image, an empty packet is sent out to jump start the
# feedback loop.
node {
  calculator: "PreviousLoopbackCalculator"
  input_stream: "MAIN:throttled_input_video"
  input_stream: "LOOP:hand_rect_from_landmarks"
  input_stream_info: {
    tag_index: "LOOP"
    back_edge: true
  }
  output_stream: "PREV_LOOP:prev_hand_rect_from_landmarks"
}

# Merges a stream of hand rectangles generated by HandDetectionSubgraph and that
# generated by HandLandmarkSubgraph into a single output stream by selecting
# between one of the two streams. The formal is selected if the incoming packet
# is not empty, i.e., hand detection is performed on the current image by
# HandDetectionSubgraph (because HandLandmarkSubgraph could not identify hand
# presence in the previous image). Otherwise, the latter is selected, which is
# never empty because HandLandmarkSubgraphs processes all images (that went
# through FlowLimiterCaculator).
node {
  calculator: "MergeCalculator"
  input_stream: "hand_rect_from_palm_detections"
  input_stream: "prev_hand_rect_from_landmarks"
  output_stream: "hand_rect"
}

# Subgraph that renders annotations and overlays them on top of the input
# images (see renderer_gpu.pbtxt).
node {
  calculator: "RendererSubgraph"
  input_stream: "IMAGE:throttled_input_video"
  input_stream: "LANDMARKS:hand_landmarks"
  input_stream: "NORM_RECT:hand_rect"
  input_stream: "DETECTIONS:palm_detections"
  output_stream: "IMAGE:output_video"
}

Hand Detection Subgraph

hand_detection_gpu_subgraph

Source pbtxt file

# MediaPipe hand detection subgraph.

type: "HandDetectionSubgraph"

input_stream: "input_video"
output_stream: "DETECTIONS:palm_detections"
output_stream: "NORM_RECT:hand_rect_from_palm_detections"

# Transforms the input image on GPU to a 256x256 image. To scale the input
# image, the scale_mode option is set to FIT to preserve the aspect ratio,
# resulting in potential letterboxing in the transformed image.
node: {
  calculator: "ImageTransformationCalculator"
  input_stream: "IMAGE_GPU:input_video"
  output_stream: "IMAGE_GPU:transformed_input_video"
  output_stream: "LETTERBOX_PADDING:letterbox_padding"
  node_options: {
    [type.googleapis.com/mediapipe.ImageTransformationCalculatorOptions] {
      output_width: 256
      output_height: 256
      scale_mode: FIT
    }
  }
}

# Generates a single side packet containing a TensorFlow Lite op resolver that
# supports custom ops needed by the model used in this graph.
node {
  calculator: "TfLiteCustomOpResolverCalculator"
  output_side_packet: "opresolver"
  node_options: {
    [type.googleapis.com/mediapipe.TfLiteCustomOpResolverCalculatorOptions] {
      use_gpu: true
    }
  }
}

# Converts the transformed input image on GPU into an image tensor stored as a
# TfLiteTensor.
node {
  calculator: "TfLiteConverterCalculator"
  input_stream: "IMAGE_GPU:transformed_input_video"
  output_stream: "TENSORS_GPU:image_tensor"
}

# Runs a TensorFlow Lite model on GPU that takes an image tensor and outputs a
# vector of tensors representing, for instance, detection boxes/keypoints and
# scores.
node {
  calculator: "TfLiteInferenceCalculator"
  input_stream: "TENSORS_GPU:image_tensor"
  output_stream: "TENSORS:detection_tensors"
  input_side_packet: "CUSTOM_OP_RESOLVER:opresolver"
  node_options: {
    [type.googleapis.com/mediapipe.TfLiteInferenceCalculatorOptions] {
      model_path: "palm_detection.tflite"
      use_gpu: true
    }
  }
}

# Generates a single side packet containing a vector of SSD anchors based on
# the specification in the options.
node {
  calculator: "SsdAnchorsCalculator"
  output_side_packet: "anchors"
  node_options: {
    [type.googleapis.com/mediapipe.SsdAnchorsCalculatorOptions] {
      num_layers: 5
      min_scale: 0.1171875
      max_scale: 0.75
      input_size_height: 256
      input_size_width: 256
      anchor_offset_x: 0.5
      anchor_offset_y: 0.5
      strides: 8
      strides: 16
      strides: 32
      strides: 32
      strides: 32
      aspect_ratios: 1.0
      fixed_anchor_size: true
    }
  }
}

# Decodes the detection tensors generated by the TensorFlow Lite model, based on
# the SSD anchors and the specification in the options, into a vector of
# detections. Each detection describes a detected object.
node {
  calculator: "TfLiteTensorsToDetectionsCalculator"
  input_stream: "TENSORS:detection_tensors"
  input_side_packet: "ANCHORS:anchors"
  output_stream: "DETECTIONS:detections"
  node_options: {
    [type.googleapis.com/mediapipe.TfLiteTensorsToDetectionsCalculatorOptions] {
      num_classes: 1
      num_boxes: 2944
      num_coords: 18
      box_coord_offset: 0
      keypoint_coord_offset: 4
      num_keypoints: 7
      num_values_per_keypoint: 2
      sigmoid_score: true
      score_clipping_thresh: 100.0
      reverse_output_order: true

      x_scale: 256.0
      y_scale: 256.0
      h_scale: 256.0
      w_scale: 256.0
      min_score_thresh: 0.7
    }
  }
}

# Performs non-max suppression to remove excessive detections.
node {
  calculator: "NonMaxSuppressionCalculator"
  input_stream: "detections"
  output_stream: "filtered_detections"
  node_options: {
    [type.googleapis.com/mediapipe.NonMaxSuppressionCalculatorOptions] {
      min_suppression_threshold: 0.3
      overlap_type: INTERSECTION_OVER_UNION
      algorithm: WEIGHTED
      return_empty_detections: true
    }
  }
}

# Maps detection label IDs to the corresponding label text ("Palm"). The label
# map is provided in the label_map_path option.
node {
  calculator: "DetectionLabelIdToTextCalculator"
  input_stream: "filtered_detections"
  output_stream: "labeled_detections"
  node_options: {
    [type.googleapis.com/mediapipe.DetectionLabelIdToTextCalculatorOptions] {
      label_map_path: "palm_detection_labelmap.txt"
    }
  }
}

# Adjusts detection locations (already normalized to [0.f, 1.f]) on the
# letterboxed image (after image transformation with the FIT scale mode) to the
# corresponding locations on the same image with the letterbox removed (the
# input image to the graph before image transformation).
node {
  calculator: "DetectionLetterboxRemovalCalculator"
  input_stream: "DETECTIONS:labeled_detections"
  input_stream: "LETTERBOX_PADDING:letterbox_padding"
  output_stream: "DETECTIONS:palm_detections"
}

# Extracts image size from the input images.
node {
  calculator: "ImagePropertiesCalculator"
  input_stream: "IMAGE_GPU:input_video"
  output_stream: "SIZE:image_size"
}

# Converts results of palm detection into a rectangle (normalized by image size)
# that encloses the palm and is rotated such that the line connecting center of
# the wrist and MCP of the middle finger is aligned with the Y-axis of the
# rectangle.
node {
  calculator: "DetectionsToRectsCalculator"
  input_stream: "DETECTIONS:palm_detections"
  input_stream: "IMAGE_SIZE:image_size"
  output_stream: "NORM_RECT:palm_rect"
  node_options: {
    [type.googleapis.com/mediapipe.DetectionsToRectsCalculatorOptions] {
      rotation_vector_start_keypoint_index: 0  # Center of wrist.
      rotation_vector_end_keypoint_index: 2  # MCP of middle finger.
      rotation_vector_target_angle_degrees: 90
      output_zero_rect_for_empty_detections: true
    }
  }
}

# Expands and shifts the rectangle that contains the palm so that it's likely
# to cover the entire hand.
node {
  calculator: "RectTransformationCalculator"
  input_stream: "NORM_RECT:palm_rect"
  input_stream: "IMAGE_SIZE:image_size"
  output_stream: "hand_rect_from_palm_detections"
  node_options: {
    [type.googleapis.com/mediapipe.RectTransformationCalculatorOptions] {
      scale_x: 2.6
      scale_y: 2.6
      shift_y: -0.5
      square_long: true
    }
  }
}

Hand Landmark Subgraph

hand_landmark_gpu_subgraph.pbtxt

Source pbtxt file

# MediaPipe hand landmark localization subgraph.

type: "HandLandmarkSubgraph"

input_stream: "IMAGE:input_video"
input_stream: "NORM_RECT:hand_rect"
output_stream: "LANDMARKS:hand_landmarks"
output_stream: "NORM_RECT:hand_rect_for_next_frame"
output_stream: "PRESENCE:hand_presence"

# Crops the rectangle that contains a hand from the input image.
node {
  calculator: "ImageCroppingCalculator"
  input_stream: "IMAGE_GPU:input_video"
  input_stream: "NORM_RECT:hand_rect"
  output_stream: "IMAGE_GPU:hand_image"
}

# Transforms the input image on GPU to a 256x256 image. To scale the input
# image, the scale_mode option is set to FIT to preserve the aspect ratio,
# resulting in potential letterboxing in the transformed image.
node: {
  calculator: "ImageTransformationCalculator"
  input_stream: "IMAGE_GPU:hand_image"
  output_stream: "IMAGE_GPU:transformed_hand_image"
  output_stream: "LETTERBOX_PADDING:letterbox_padding"
  node_options: {
    [type.googleapis.com/mediapipe.ImageTransformationCalculatorOptions] {
      output_width: 256
      output_height: 256
      scale_mode: FIT
    }
  }
}

# Converts the transformed input image on GPU into an image tensor stored as a
# TfLiteTensor.
node {
  calculator: "TfLiteConverterCalculator"
  input_stream: "IMAGE_GPU:transformed_hand_image"
  output_stream: "TENSORS_GPU:image_tensor"
}

# Runs a TensorFlow Lite model on GPU that takes an image tensor and outputs a
# vector of tensors representing, for instance, detection boxes/keypoints and
# scores.
node {
  calculator: "TfLiteInferenceCalculator"
  input_stream: "TENSORS_GPU:image_tensor"
  output_stream: "TENSORS:output_tensors"
  node_options: {
    [type.googleapis.com/mediapipe.TfLiteInferenceCalculatorOptions] {
      model_path: "hand_landmark.tflite"
      use_gpu: true
    }
  }
}

# Splits a vector of tensors into multiple vectors.
node {
  calculator: "SplitTfLiteTensorVectorCalculator"
  input_stream: "output_tensors"
  output_stream: "landmark_tensors"
  output_stream: "hand_flag_tensor"
  node_options: {
    [type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
      ranges: { begin: 0 end: 1 }
      ranges: { begin: 1 end: 2 }
    }
  }
}

# Converts the hand-flag tensor into a float that represents the confidence
# score of hand presence.
node {
  calculator: "TfLiteTensorsToFloatsCalculator"
  input_stream: "TENSORS:hand_flag_tensor"
  output_stream: "FLOAT:hand_presence_score"
}

# Applies a threshold to the confidence score to determine whether a hand is
# present.
node {
  calculator: "ThresholdingCalculator"
  input_stream: "FLOAT:hand_presence_score"
  output_stream: "FLAG:hand_presence"
  node_options: {
    [type.googleapis.com/mediapipe.ThresholdingCalculatorOptions] {
      threshold: 0.1
    }
  }
}

# Decodes the landmark tensors into a vector of lanmarks, where the landmark
# coordinates are normalized by the size of the input image to the model.
node {
  calculator: "TfLiteTensorsToLandmarksCalculator"
  input_stream: "TENSORS:landmark_tensors"
  output_stream: "NORM_LANDMARKS:landmarks"
  node_options: {
    [type.googleapis.com/mediapipe.TfLiteTensorsToLandmarksCalculatorOptions] {
      num_landmarks: 21
      input_image_width: 256
      input_image_height: 256
    }
  }
}

# Adjusts landmarks (already normalized to [0.f, 1.f]) on the letterboxed hand
# image (after image transformation with the FIT scale mode) to the
# corresponding locations on the same image with the letterbox removed (hand
# image before image transformation).
node {
  calculator: "LandmarkLetterboxRemovalCalculator"
  input_stream: "LANDMARKS:landmarks"
  input_stream: "LETTERBOX_PADDING:letterbox_padding"
  output_stream: "LANDMARKS:scaled_landmarks"
}

# Projects the landmarks from the cropped hand image to the corresponding
# locations on the full image before cropping (input to the graph).
node {
  calculator: "LandmarkProjectionCalculator"
  input_stream: "NORM_LANDMARKS:scaled_landmarks"
  input_stream: "NORM_RECT:hand_rect"
  output_stream: "NORM_LANDMARKS:hand_landmarks"
}

# Extracts image size from the input images.
node {
  calculator: "ImagePropertiesCalculator"
  input_stream: "IMAGE_GPU:input_video"
  output_stream: "SIZE:image_size"
}

# Converts hand landmarks to a detection that tightly encloses all landmarks.
node {
  calculator: "LandmarksToDetectionCalculator"
  input_stream: "NORM_LANDMARKS:hand_landmarks"
  output_stream: "DETECTION:hand_detection"
}

# Converts the hand detection into a rectangle (normalized by image size)
# that encloses the hand and is rotated such that the line connecting center of
# the wrist and MCP of the middle finger is aligned with the Y-axis of the
# rectangle.
node {
  calculator: "DetectionsToRectsCalculator"
  input_stream: "DETECTION:hand_detection"
  input_stream: "IMAGE_SIZE:image_size"
  output_stream: "NORM_RECT:hand_rect_from_landmarks"
  node_options: {
    [type.googleapis.com/mediapipe.DetectionsToRectsCalculatorOptions] {
      rotation_vector_start_keypoint_index: 0  # Center of wrist.
      rotation_vector_end_keypoint_index: 9  # MCP of middle finger.
      rotation_vector_target_angle_degrees: 90
    }
  }
}

# Expands the hand rectangle so that in the next video frame it's likely to
# still contain the hand even with some motion.
node {
  calculator: "RectTransformationCalculator"
  input_stream: "NORM_RECT:hand_rect_from_landmarks"
  input_stream: "IMAGE_SIZE:image_size"
  output_stream: "hand_rect_for_next_frame"
  node_options: {
    [type.googleapis.com/mediapipe.RectTransformationCalculatorOptions] {
      scale_x: 1.6
      scale_y: 1.6
      square_long: true
    }
  }
}

Renderer Subgraph

hand_renderer_gpu_subgraph.pbtxt

Source pbtxt file

# MediaPipe hand tracking rendering subgraph.

type: "RendererSubgraph"

input_stream: "IMAGE:input_image"
input_stream: "DETECTIONS:detections"
input_stream: "LANDMARKS:landmarks"
input_stream: "NORM_RECT:rect"
output_stream: "IMAGE:output_image"

# Converts detections to drawing primitives for annotation overlay.
node {
  calculator: "DetectionsToRenderDataCalculator"
  input_stream: "DETECTIONS:detections"
  output_stream: "RENDER_DATA:detection_render_data"
  node_options: {
    [type.googleapis.com/mediapipe.DetectionsToRenderDataCalculatorOptions] {
      thickness: 4.0
      color { r: 0 g: 255 b: 0 }
    }
  }
}

# Converts landmarks to drawing primitives for annotation overlay.
node {
  calculator: "LandmarksToRenderDataCalculator"
  input_stream: "NORM_LANDMARKS:landmarks"
  output_stream: "RENDER_DATA:landmark_render_data"
  node_options: {
    [type.googleapis.com/mediapipe.LandmarksToRenderDataCalculatorOptions] {
      landmark_connections: 0
      landmark_connections: 1
      landmark_connections: 1
      landmark_connections: 2
      landmark_connections: 2
      landmark_connections: 3
      landmark_connections: 3
      landmark_connections: 4
      landmark_connections: 0
      landmark_connections: 5
      landmark_connections: 5
      landmark_connections: 6
      landmark_connections: 6
      landmark_connections: 7
      landmark_connections: 7
      landmark_connections: 8
      landmark_connections: 5
      landmark_connections: 9
      landmark_connections: 9
      landmark_connections: 10
      landmark_connections: 10
      landmark_connections: 11
      landmark_connections: 11
      landmark_connections: 12
      landmark_connections: 9
      landmark_connections: 13
      landmark_connections: 13
      landmark_connections: 14
      landmark_connections: 14
      landmark_connections: 15
      landmark_connections: 15
      landmark_connections: 16
      landmark_connections: 13
      landmark_connections: 17
      landmark_connections: 0
      landmark_connections: 17
      landmark_connections: 17
      landmark_connections: 18
      landmark_connections: 18
      landmark_connections: 19
      landmark_connections: 19
      landmark_connections: 20
      landmark_color { r: 255 g: 0 b: 0 }
      connection_color { r: 0 g: 255 b: 0 }
      thickness: 4.0
    }
  }
}

# Converts normalized rects to drawing primitives for annotation overlay.
node {
  calculator: "RectToRenderDataCalculator"
  input_stream: "NORM_RECT:rect"
  output_stream: "RENDER_DATA:rect_render_data"
  node_options: {
    [type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
      filled: false
      color { r: 255 g: 0 b: 0 }
      thickness: 4.0
    }
  }
}

# Draws annotations and overlays them on top of the input images.
node {
  calculator: "AnnotationOverlayCalculator"
  input_stream: "INPUT_FRAME_GPU:input_image"
  input_stream: "detection_render_data"
  input_stream: "landmark_render_data"
  input_stream: "rect_render_data"
  output_stream: "OUTPUT_FRAME_GPU:output_image"
}

204 comments

  1. You should take part in a contest for one
    of the highest quality sites on the net. I’m going to recommend this blog!

  2. Excellent pieces. Keeр writing such kind
    of info on yoᥙr bloց. Im really impressed by your blog.

    Hey there, You’ve done an exceⅼlent job. I’ll certaonly digg it
    and foг my part recommend to my friends. I am sude they’ll be benefited from this web site.

  3. Pretty nice post. I just stumbled upon your weblog and wished to mention that I
    have really enjoyed surfing around your weblog posts.
    After all I’ll be subscribing for your feed and I am hoping you write again soon!

  4. Hmm is anyone else having problems with the
    pictures on this blog loading? I’m trying to figure out if its a problem on my
    end or if it’s the blog. Any feedback would be greatly appreciated.

  5. Hi there very cool website!! Guy .. Excellent ..
    Wonderful .. I will bookmark your site and take the feeds additionally…I’m glad to search out a lot of useful information here in the post,
    we need work out more techniques in this regard, thanks for sharing.

    Stop by my web page Gold Leaf CBD

  6. What’s up it’s me, I am also visiting this website daily, this web
    page is in fact good and the viewers are actually
    sharing pleasant thoughts.

    my web-site: Keeley

  7. I enjoy you because of all your work on this site. My niece
    really loves engaging in research and it’MosQiller S Review really obvious why.

    Most people learn all about the dynamic mode
    you present very helpful information by means of this web blog
    and therefore invigorate contribution from the others about this theme and our own girl is without a doubt
    studying a whole lot. Have fun with the remaining portion of
    the year. Your performing a pretty cool job.[X-N-E-W-L-I-N-S-P-I-N-X]I am really inspired together
    with your writing talents and also with the format in your weblog.

    Is this a paid topic or did you customize it your self? Either
    way keep up the excellent high quality writing, it is rare to look a nice weblog like this one these days.

  8. Hello I am so excited I found your web site, I really
    found you by error, while I was researching on Yahoo for something else, Anyways I am here now
    and would just like to say thanks a lot for a incredible post and a all round enjoyable blog (I also love the theme/design), I don?t have time to look over it all
    at the minute but I have book-marked it and also included your
    RSS feeds, so when I have time I will be back to read a lot more,
    Please do keep up the great jo.

    Feel free to surf to my website: UltraCut Keto

  9. Hey There. I found your blog using msn. This is an extremely well
    written article. I will be sure to bookmark it and come back to read more of your useful info.
    Thanks for the post. I’ll definitely comeback.

    my site … DFine8

  10. I like the valuable info you supply on your articles.
    I’ll bookmark your weblog and test once more right here
    regularly. I’m rather certain I’ll be informed many new stuff proper here!
    Good luck for the following!

    Here is my blog; Keto LeanX

  11. I’m impressed, I have to admit. Rarely do I come across a blog that’s both educative and interesting,
    and let me tell you, you’ve hit the nail on the head.
    The issue is something that not enough men and women are speaking intelligently about.
    I am very happy that I stumbled across this during my search for something relating to
    this.

    Also visit my web-site; Gold Leaf CBD

  12. Terrific work! This is the type of info that are supposed to be shared around the web.
    Disgrace on the seek engines for not positioning this post upper!
    Come on over and seek advice from my site . Thanks =)

    Feel free to visit my web page – Green Earth CBD

  13. Heya! I’m at work browsing your blog from my new apple iphone!
    Just wanted to say I love reading your blog and
    look forward to all your posts! Keep up the great work!

    Visit my web-site – Anitra

  14. I must thank you for the efforts you have put in penning this website.
    I’m hoping to see the same high-grade blog posts
    by you later on as well. In fact, your creative
    writing abilities has motivated me to get my own, personal site now ;
    )

    Here is my web site; Sion Cooler

  15. Hey I am so thrilled I found your site, I really found you by error, while I was researching
    on Google for something else, Anyways I am here now and would just like to say many thanks for a incredible post
    and a all round entertaining blog (I also love the theme/design),
    I don’t have time to read through it all at the moment but I have
    saved it and also added in your RSS feeds, so when I have time I will be back to read much more,
    Please do keep up the fantastic job.

    Also visit my web site; http://www.comptine.biz

  16. Simply want to say your article is as amazing.
    The clearness on your put up is simply cool and that i could
    suppose you’re a professional on this subject. Well together with your permission allow
    me to take hold of your feed to stay up to date with approaching post.
    Thanks one million and please carry on the rewarding work.

    Here is my web site – Virectin

  17. Everything posted was actually very reasonable. However, think on this, what if you added
    a little content? I am not suggesting your information is not solid., however what if you added a
    title to possibly get a person’s attention? I mean GitHub
    Open-Source Code for Hand Gesture Recognition ?

    Sign Language Translation – Pavvy Designs is a
    little vanilla. You ought to glance at Yahoo’s home page and
    note how they create article titles to get people interested.
    You might add a video or a picture or two to get people interested about what you’ve got to
    say. In my opinion, it could bring your website a little
    livelier.

    my page; Amellia Cream Reviews (web.jmjh.tn.edu.tw)

  18. Great site you have here but I was curious about if you knew of any message boards that cover the same topics discussed here?
    I’d really like to be a part of community where I can get comments from other
    experienced individuals that share the same interest.

    If you have any recommendations, please let me know.
    Thank you!

    my page – Re ViVium

  19. Hey there! Someone in my Myspace group shared this site with us
    so I came to give it a look. I’m definitely enjoying the information. I’m book-marking and will be
    tweeting this to my followers! Great blog and
    brilliant style and design.

    Take a look at my website – Vigalix Review

  20. I am not sure where you’re getting your information, but good topic.
    I needs to spend some time learning more or understanding more.
    Thanks for fantastic information I was looking for this info for my mission.

    my website … DFine8

  21. you’re actually a excellent webmaster. The site loading velocity is amazing.
    It sort of feels that you’re doing any distinctive trick.
    In addition, The contents are masterpiece. you have done a fantastic activity
    in this topic!

    My homepage; fotosombra.com.br

  22. I think that is one of the so much significant information for
    me. And i’m satisfied reading your article. However
    wanna commentary on some common issues, The web site taste is wonderful,
    the articles is in reality excellent : D. Good activity, cheers

    my web-site: Compoise CBD Gummies

  23. I am also commenting to let you understand of the nice discovery my
    wife’s princess obtained reading through your webblog.
    She realized too many issues, including what it
    is like to possess an awesome giving style to have certain people with ease completely grasp several
    specialized issues. You really did more than my expected results.
    Many thanks for rendering these productive, trustworthy, educational
    not to mention unique guidance on the topic to Mary.

    Here is my page … Bio Wellness CBD

  24. What i don’t realize is in truth how you’re
    now not actually a lot more neatly-liked than you may
    be now. You’re so intelligent. You already know thus considerably
    in terms of this subject, made me in my opinion imagine it from numerous numerous angles.
    Its like women and men are not involved until it
    is one thing to do with Lady gaga! Your individual stuffs nice.
    At all times deal with it up!

    My page: bibliodigital.escoladocaminho.com

  25. This is really interesting, You are a very skilled blogger.
    I’ve joined your rss feed and look forward to seeking more of your
    fantastic post. Also, I’ve shared your web site in my social networks!

    Look into my blog post :: srdon.ru

  26. Hi! This is my 1st comment here so I just wanted
    to give a quick shout out and say I really enjoy reading your blog posts.
    Can you recommend any other blogs/websites/forums that go over the same subjects?
    Thanks a lot!

    My blog … VigorMax

  27. I’ve been surfing online more than three hours lately,
    yet I by no means found any fascinating article like
    yours. It’s pretty value sufficient for me. In my opinion, if
    all webmasters and bloggers made excellent
    content as you probably did, the net can be a lot more helpful than ever
    before.

    Also visit my site – http://www.hotelforrest.ru

  28. Hey I know this is off topic but I was wondering if you knew of any widgets I could add to my blog that automatically tweet my newest twitter updates.
    I’ve been looking for a plug-in like this for quite some time and was hoping maybe you would have some experience with
    something like this. Please let me know if you run into anything.
    I truly enjoy reading your blog and I look forward to your new updates.

    Review my web page … librarius.main.jp

  29. I needed to post you one very small word in order to thank you so much the moment again just
    for the pleasing things you’ve provided in this case.

    This is really incredibly generous of you to provide publicly what
    exactly most people could have offered for sale as an e-book to
    help with making some profit for themselves, mostly now that you
    could possibly have tried it if you ever considered necessary.

    The tactics additionally acted to become good way to recognize that most people have similar keenness much like my very own to
    know a whole lot more on the topic of this condition. I am
    certain there are many more pleasant situations up front for those who take a
    look at your blog.

    Check out my web site SuperCharged IQ

  30. Great – I should certainly pronounce, impressed with your web
    site. I had no trouble navigating through all the tabs as well as related information ended up being truly simple
    to do to access. I recently found what I hoped for before you know it in the
    least. Reasonably unusual. Is likely to appreciate it
    for those who add forums or anything, site theme . a tones way for
    your customer to communicate. Excellent task.

    My web-site :: duna-anapa.net.ru

  31. Pretty portion of content. I simply stumbled upon your website and in accession capital to assert that I acquire actually loved account your blog posts.
    Anyway I will be subscribing to your feeds and even I
    fulfillment you get admission to persistently rapidly.

  32. I wanted to check up and allow you to know how , very much I loved discovering your web blog today.
    I will consider it the honor to work at my office and be able
    to make real use of the tips contributed on your website and also engage in visitors’ responses like this.

    Should a position connected with guest author become on offer at your end,
    remember to let me know.

    Feel free to visit my site Wawaza Apple Cider Gummies

  33. hey there and thank you for your info ? I have certainly picked
    up something new from right here. I did however expertise some technical
    issues using this web site, as I experienced to reload the
    web site many times previous to I could get it to load correctly.
    I had been wondering if your hosting is OK? Not that I’m complaining, but sluggish
    loading instances times will sometimes affect your placement
    in google and can damage your high quality score if advertising and marketing with Adwords.
    Anyway I’m adding this RSS to my e-mail and could look out for much more of your
    respective exciting content. Make sure you update this again very soon.

    Feel free to visit my webpage … Aja

  34. Thanks for any other informative blog. Where else may I get
    that type of information written in such an ideal manner?
    I’ve a challenge that I’m simply now operating on, and
    I’ve been on the glance out for such information.

  35. Hi there, I found your blog by way of Google even as searching for a similar subject, your website got here up, it looks good.
    I’ve bookmarked it in my google bookmarks.
    Hi there, just changed into alert to your blog
    through Google, and found that it’s truly informative. I am gonna
    be careful for brussels. I’ll appreciate should
    you proceed this in future. A lot of people will likely be benefited from your writing.
    Cheers!

  36. I just wanted to type a quick note in order to say thanks to you
    for these magnificent recommendations you are placing at this
    website. My extensive internet look up has at the end been paid with
    sensible suggestions to go over with my classmates and friends.
    I would express that many of us visitors actually are unquestionably blessed to exist in a magnificent place with
    very many outstanding individuals with insightful concepts.
    I feel very much fortunate to have encountered
    your entire web pages and look forward to plenty of more cool minutes reading here.
    Thanks a lot again for everything.

    Feel free to visit my web blog Yec Keto Ingredients

  37. Hello! I just wanted to ask if you ever have any trouble with hackers?
    My last blog (wordpress) was hacked and I ended up losing a few
    months of hard work due to no data backup. Do you have any methods to stop hackers?

    Here is my web blog EcoHack Review

  38. Greetings! This is my first comment here so I just wanted to give a quick
    shout out and tell you I truly enjoy reading your
    blog posts. Can you suggest any other blogs/websites/forums that deal
    with the same subjects? Thanks!

    Here is my site; Keto Speed Diet

  39. Just to follow up on the up-date of this topic on your web site
    and would like to let you know simply how much
    I valued the time you took to publish this beneficial post.

    Inside the post, you spoke of how to truly handle this concern with all ease.
    It would be my personal pleasure to accumulate some more suggestions from
    your web site and come as much as offer others what I
    have benefited from you. Many thanks for your usual wonderful effort.

    Feel free to surf to my blog post :: http://www.tpspa.net/

  40. Hey! Someone in my Facebook group shared this site with us so I came to give
    it a look. I’m definitely enjoying the information. I’m bookmarking and will be
    tweeting this to my followers! Superb blog and outstanding design.

    my page EcoHack Chip

  41. Greetings, I believe your blog may be having internet browser compatibility problems.
    When I look at your site in Safari, it looks fine however when opening in Internet Explorer, it’s got some overlapping issues.
    I merely wanted to give you a quick heads up! Besides that, wonderful blog!

  42. I would like to thank you for the efforts you’ve put in penning this site.

    I am hoping to see the same high-grade content by you
    in the future as well. In fact, your creative writing abilities has inspired me to get my very own blog now ;
    )

  43. I was recommended this web site by my cousin. I’m now not sure whether or not this submit is
    written by way of him as nobody else recognise such particular approximately my difficulty.
    You are incredible! Thank you!

    Also visit my web site … Vi-Alpha

  44. Heya are using WordPress for your blog platform?
    I’m new to the blog world but I’m trying to get started and set up
    my own. Do you need any coding knowledge to make your own blog?
    Any help would be greatly appreciated!

  45. What i don’t realize is in reality how you are not actually a
    lot more neatly-preferred than you may be right now.
    You’re so intelligent. You already know therefore considerably in relation to this topic, made me personally consider it from numerous varied angles.
    Its like women and men don’t seem to be fascinated unless it’s something to accomplish with Girl gaga!
    Your personal stuffs excellent. Always deal with it
    up!

  46. My developer is trying to persuade me to move to .net from PHP.
    I have always disliked the idea because of the costs.

    But he’s tryiong none the less. I’ve been using Movable-type on a
    number of websites for about a year and am nervous about switching to another platform.
    I have heard excellent things about blogengine.net. Is there a way I can import all my wordpress content into it?
    Any help would be really appreciated!

    Feel free to visit my webpage – Far East XL Male Enhancement

  47. If you desire to improve your experience only keep visiting
    this website and be updated with the newest news posted here.

  48. Hi! This post could not be written any better! Reading through this
    post reminds me of my good old room mate! He always kept talking
    about this. I will forward this post to him.
    Pretty sure he will have a good read. Thanks for sharing!

    Here is my web-site: Extreme Muscle XXL

  49. I don’t know if it’s just me or if perhaps everybody else encountering issues with your site.
    It looks like some of the written text in your content are
    running off the screen. Can somebody else please comment and let me know if
    this is happening to them too? This may be a issue with my web browser because
    I’ve had this happen before. Appreciate it

  50. Hi! I could have sworn I’ve been to this blog before but after going through some of the posts I realized it’s new to me.
    Nonetheless, I’m definitely happy I discovered it and I’ll
    be bookmarking it and checking back often!

    my web-site :: Keto Incinerate

  51. I’d been honored to obtain a call coming from a friend as soon as
    he identified the important suggestions shared on the site.
    Examining your blog write-up is a real great experience.

    Many thanks for considering readers at all like me,
    and I want for you the best of achievements for a professional in this domain.

    Feel free to surf to my blog post :: Captive Skin Cream

  52. Excellent way of explaining, and pleasant post to take data
    concerning my presentation subject, which i am going to deliver in academy.

    Look into my homepage: Zelda

  53. Please let me know if you’re looking for a author for your weblog.

    You have some really good articles and I feel I would be a good asset.
    If you ever want to take some of the load off, I’d absolutely love to write some articles for your
    blog in exchange for a link back to mine.
    Please shoot me an e-mail if interested. Regards!

    Also visit my homepage; Androrexin Advanced

  54. Right now it sounds like WordPress is the best
    blogging platform out there right now. (from what I’ve read) Is that what
    you are using on your blog?

    Look at my site :: hltkd.tw

  55. Greetings I am so thrilled I found your webpage,
    I really found you by accident, while I was browsing on Yahoo for something else, Anyhow
    I am here now and would just like to say thanks for a
    tremendous post and a all round exciting blog (I also
    love the theme/design), I don’t have time to read through it all at the moment but
    I have bookmarked it and also included your RSS feeds, so when I have time I will be
    back to read a lot more, Please do keep up the awesome
    b. asmr https://app.gumroad.com/asmr2021/p/best-asmr-online asmr

  56. I blog frequently and I genuinely thank you for your content.
    This article has really peaked my interest.
    I will book mark your website and keep checking for new details about once per
    week. I opted in for your RSS feed too.

    my website – Max BHB

  57. I’m curious to find out what blog platform you happen to be
    using? I’m experiencing some small security issues with my latest website and I’d like to find something more risk-free.
    Do you have any suggestions? scoliosis surgery https://0401mm.tumblr.com/ scoliosis surgery

  58. Pretty component to content. I simply stumbled upon your site
    and in accession capital to claim that I get
    in fact loved account your weblog posts. Any way I’ll be subscribing in your feeds
    or even I achievement you get right of entry to consistently fast.

    my web blog – pansionat.com.ru

  59. Thanks for every other informative site. The place else may just
    I get that type of info written in such a perfect means?
    I’ve a undertaking that I am simply now running on, and
    I’ve been on the glance out for such information. ps4 https://bitly.com/3z5HwTp ps4 games

  60. I’m not sure exactly why but this web site is loading incredibly slow
    for me. Is anyone else having this issue or is it a problem on my end?
    I’ll check back later on and see if the problem still exists.

    Also visit my web page :: Garnet

  61. Great ? I should certainly pronounce, impressed with your site.
    I had no trouble navigating through all the tabs as well as related info ended up being truly simple to do
    to access. I recently found what I hoped for before you know it
    at all. Quite unusual. Is likely to appreciate it for those who add forums or anything,
    web site theme . a tones way for your customer to communicate.
    Nice task.

    Also visit my web site :: http://23.95.102.216/viewtopic.php?id=108146

  62. Write more, thats all I have to say. Literally, it seems
    as though you relied on the video to make your
    point. You clearly know what youre talking about,
    why waste your intelligence on just posting videos to your blog when you could be giving us something informative to read?

    Also visit my web site :: aging skin

  63. Hey just wanted to give you a brief heads up and let you know a few of the pictures aren’t loading correctly.

    I’m not sure why but I think its a linking issue.
    I’ve tried it in two different internet browsers and both show the same outcome.

    Feel free to visit my website :: http://www.goldenanapa.ru

  64. Thanks for every other informative blog. Where else may just I
    get that type of info written in such a perfect method?
    I’ve a venture that I’m just now running on, and I’ve been on the glance out for such information.

    Stop by my website: facial care

  65. Hello! I just wanted to ask if you ever have any trouble with hackers?
    My last blog (wordpress) was hacked and I ended up losing many months of hard work due to no
    data backup. Do you have any solutions to protect against
    hackers?

    Also visit my blog; seeds starts

  66. My brother suggested I might like this website. He was totally right.
    This post actually made my day. You cann’t imagine simply how
    much time I had spent for this info! Thanks!

    My homepage :: hemp seed

  67. I wanted to follow up and allow you to know how really I loved
    discovering your blog today. I might consider it a good honor to operate at my place of
    work and be able to utilize the tips discussed on your blog and also participate in visitors’
    remarks like this. Should a position of guest publisher become on offer at your end, please
    let me know.

    Feel free to surf to my web page; teen weightloss

  68. hey there and thank you for your information ? I?ve definitely
    picked up anything new from right here. I did however expertise a
    few technical issues using this website, since I experienced to reload the site lots of times previous to I could get it to load correctly.
    I had been wondering if your web hosting is OK?

    Not that I am complaining, but sluggish loading
    instances times will very frequently affect your placement in google and could damage your high-quality score if advertising and marketing with Adwords.
    Well I?m adding this RSS to my email and could look out for a lot more of your respective
    intriguing content. Ensure that you update this again soon..

    Feel free to surf to my web page; web.treo8.com

  69. Unquestionably believe that which you said. Your favorite justification seemed to be on the web the easiest
    thing to be aware of. I say to you, I definitely get
    irked while people consider worries that they just do not know about.
    You managed to hit the nail upon the top and defined out the whole thing without having side effect ,
    people can take a signal. Will probably be back to get
    more. Thanks

    Review my web site; stop smoking weed everyday

  70. I do not even understand how I stopped up right here, but I believed this
    put up used to be good. I don’t understand who you’re but certainly you are going to a famous blogger
    if you are not already 😉 Cheers!

    my web-site; a913.vip

  71. Thank you so much for providing individuals with an exceptionally terrific
    opportunity to read critical reviews from this web site.
    It is always so pleasing and full dangers of a protein diet a great
    time for me and my office friends to visit your
    website really 3 times every week to study the newest guides you will have.

    And indeed, we are at all times motivated concerning
    the attractive tactics you give. Some 2 facts on this
    page are completely the most suitable we have all ever had.

  72. Hello there, I discovered your web site via Google whilst searching for a similar subject, your
    web site came up, it seems to be great. I have
    bookmarked it in my google bookmarks.[X-N-E-W-L-I-N-S-P-I-N-X]Hello there,
    just became aware of your blog thru Google, and located that it is really informative.
    I’m going to watch out for brussels. I’ll appreciate should you
    proceed this in future. Lots of people will be benefited out of your writing.
    Cheers!

    Here is my web blog: prettypeople.club

  73. I have been surfing online more than three hours as of
    late, but I never found any attention-grabbing article like yours.
    It is pretty price enough for me. In my opinion, if all website
    owners and bloggers made good content material as you did,
    the web will be a lot more useful than ever before.

    my web blog; low carb dieting tips

  74. Thank you for every other informative blog. The place else may I am getting that type of information written in such a perfect
    means? I have a project that I’m just now working on, and
    I’ve been at the glance out for such information.

    Feel free to surf to my blog post :: eat healthy foods

  75. It is the best time to make some plans for the future
    and it is time to be happy. I have read this post and if I
    could I want to suggest you few interesting things
    or advice. Maybe you can write next articles referring to this article.
    I desire to read even more things about it!

    Here is my blog … kids smoking

  76. I got this website from my pal who told me regarding this site and at the moment this time I am visiting this website and reading very informative articles
    at this time.

    My web page: Craig

  77. I love your blog.. very nice colors & theme. Did you make this website yourself or did you hire someone to do
    it for you? Plz reply as I’m looking to create my own blog and would like to find out where u got this from.
    appreciate it

    Feel free to surf to my blog :: diets bullshit

  78. Pingback: green beans keto

Leave a Reply

Your email address will not be published.