{"id":24508404,"url":"https://github.com/frankson18/virtual-puzzle-on-google-meet-with-python-and-opencv","last_synced_at":"2026-05-03T07:41:57.758Z","repository":{"id":139861415,"uuid":"403779784","full_name":"Frankson18/Virtual-Puzzle-on-google-meet-with-python-and-opencv","owner":"Frankson18","description":"Trabalho final da disciplina de Processamento digital de imagens da UFRN. Inspirado no vídeo do MurtazasWorkshopRoboticsandAI, o quebra-cabeça virtual é um programa que faz com que o usuário consiga manipular fotos presentes no seu visor utilizando o movimento de suas mãos, assim sendo possível criar um quebra-cabeça para ser montado.","archived":false,"fork":false,"pushed_at":"2021-09-06T23:59:04.000Z","size":4442,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-22T00:15:44.320Z","etag":null,"topics":["cvzone","google-meet","opencv","processing-images","puzzle-game","python","virtualcamera"],"latest_commit_sha":null,"homepage":"https://frankson18.github.io/Virtual-Puzzle-on-google-meet-with-python-and-opencv/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Frankson18.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-06T23:09:52.000Z","updated_at":"2023-08-17T10:08:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"241b5840-e63c-4085-a3da-2835b385fff3","html_url":"https://github.com/Frankson18/Virtual-Puzzle-on-google-meet-with-python-and-opencv","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frankson18%2FVirtual-Puzzle-on-google-meet-with-python-and-opencv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frankson18%2FVirtual-Puzzle-on-google-meet-with-python-and-opencv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frankson18%2FVirtual-Puzzle-on-google-meet-with-python-and-opencv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frankson18%2FVirtual-Puzzle-on-google-meet-with-python-and-opencv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Frankson18","download_url":"https://codeload.github.com/Frankson18/Virtual-Puzzle-on-google-meet-with-python-and-opencv/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243707895,"owners_count":20334718,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cvzone","google-meet","opencv","processing-images","puzzle-game","python","virtualcamera"],"created_at":"2025-01-22T00:15:55.966Z","updated_at":"2026-05-03T07:41:52.724Z","avatar_url":"https://github.com/Frankson18.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Virtual Puzzle on google meet with python and opencv\n\n# INTRODUÇÃO\n\nTrabalho final da disciplina de Processamento digital de imagens da UFRN. Inspirado no vídeo do [MurtazasWorkshopRoboticsandAI](https://www.youtube.com/watch?v=6DxN8G9vB50\u0026t=87s), o quebra-cabeça virtual é um programa que faz com que o usuário consiga manipular fotos presentes no seu visor utilizando o movimento de suas mãos, assim sendo possível criar um quebra-cabeça para ser montado.\n\n### **Exemplo de funcionamento:**\n\n![ezgif.com-gif-maker.gif](Virtual%20Puzzle%20on%20google%20meet%20with%20python%20and%20open%20001108725ca94819a65e9cfead454e68/ezgif.com-gif-maker.gif)\n\n# COMO UTILIZAR\n\npara poder utilizar você vai ter instalado o `python`, eu utilizei a `versão 3.9`, o programa de captura de tela `OBS` para gerar a câmera virtual para usar no meet e instalar no python a biblioteca `cvzone versão 1.4`.\n\nPara exemplo utilizei uma imagem 1000x200 com o nome [test.jpg](https://saskatoonfood.ca/images/headers/1000x200-StoonDusk.jpg), assim quando for executar e tiver outra imagem basta muda o endereço no código.\n\n### Passo a passo\n\n1. abri o OBS e iniciar a câmera virtual\n2. executar o código python\n3. se divertir com o a montagem do quebra-cabeça\n\ncaso queria ver o passo a passo pode assistir o vídeo: \n\n[https://www.youtube.com/watch?v=5MpKMHGrYTk](https://www.youtube.com/watch?v=5MpKMHGrYTk)\n\n# FUNCIONAMENTO DO CÓDIGO\n\n```python\nimport cv2\nimport cvzone\nimport pyvirtualcam\nfrom pyvirtualcam import PixelFormat\nfrom cvzone.HandTrackingModule import HandDetector # detectar mãos\n\ncap = cv2.VideoCapture(0)\ncap.set(3, 1280)\ncap.set(4, 720)\n\ndetector = HandDetector(detectionCon=0.7) #precisão de 70%\n\nclass imgObject():\n    #iniciando varaiveis da imagem\n    def __init__(self,posCenter,size=[200,200]):\n        self.posCenter = posCenter\n        self.size = size\n\n    def updata(self,cursor):\n        cx,cy = self.posCenter\n        w,h = self.size\n\n        # conferir se o dedo esta em cima da imagem e move para a posição do dedo\n        if cx - w // 2 \u003c cursor[0] \u003c cx + w // 2 and cy - h // 2 \u003c cursor[1] \u003c cy + h // 2 :\n            self.posCenter = cursor\n\nimgList = []\n\n#preparando a imagem para o quebra cabeça\nimagem = cv2.imread(\"test.jpg\")\nimagem1 = imagem[0:200,0:200]\nimagem2 = imagem[0:200,200:400]\nimagem3 = imagem[0:200,400:600]\nimagem4 = imagem[0:200,600:800]\nimagem5 = imagem[0:200,800:1000]\ncv2.imwrite(\"test3.jpg\",imagem1)\ncv2.imwrite(\"test4.jpg\",imagem2)\ncv2.imwrite(\"test1.jpg\",imagem3)\ncv2.imwrite(\"test2.jpg\",imagem4)\ncv2.imwrite(\"test0.jpg\",imagem5)\n\nfor x in range(5):\n    imgList.append(imgObject([x*250+150,150]))\n\nwith pyvirtualcam.Camera(width=1280, height=720, fps=24, fmt=PixelFormat.BGR) as cam:\n    while True:\n        success, img = cap.read()\n        img = detector.findHands(img)\n        lmList, _ = detector.findPosition(img) # posição da mão e dos dedos\n\n        if lmList:\n            l, _, _ = detector.findDistance(8,12,img,draw=False) # conta a distancia dos dedos\n\n            #conferir se os dedos estão juntos ou não (click)\n            if l \u003c 40 :\n                cursor = lmList[8] #posição do dedo indicador\n                # atualiza a posição\n                for rect in imgList:\n                    rect.updata(cursor)\n        try:\n            #desenhar imagem na tela\n            for i, rect in enumerate(imgList):\n                filename = \"test%d.jpg\" % i\n                cx, cy = rect.posCenter\n                w, h = rect.size\n                imagem = cv2.imread(filename)\n                imagem = cv2.flip(imagem, 1)\n                img[cy-h//2:cy+h//2,cx-w//2:cx+w//2] = imagem.copy()\n\n                #parte verde do retangulo\n                cvzone.cornerRect(img,(cx-w//2,cy-h//2,w,h),20,rt=0)\n        except:\n            pass\n\n        cam.send(img)\n        cam.sleep_until_next_frame()\n\n        cv2.waitKey(1)\n```\n\n---\n\nComeço com a importação das bibliotecas necessárias para o funcionamento: `cv2` para o `opencv`, `cvzone` para poder utilizar bibliotecas de visão computacional,`pyvirtualcam` para criar a câmera virtual.\n\n```python\nimport cv2\nimport cvzone\nimport pyvirtualcam\nfrom pyvirtualcam import PixelFormat\nfrom cvzone.HandTrackingModule import HandDetector # detectar mãos\n```\n\n---\n\nlogo após inicio a variável de captura o vídeo da webcam e seleciono o seu tamanho para ser 1280x720 e também inicializo a função que responsável por detectar minha mão com 70% de precisão.\n\n```python\ncap = cv2.VideoCapture(0)\ncap.set(3, 1280)\ncap.set(4, 720)\n\ndetector = HandDetector(detectionCon=0.7) #precisão de 70%\n```\n\n---\n\nAqui eu crio a classe `imgObject` responsável por guarda todas as informações importantes para minha imagem, e o método `update` que atualiza a posição central da imagem, que vamos usar para poder fazer seu movimento na tela, futuramente.\n\n```python\nclass imgObject():\n    #iniciando varaiveis da imagem\n    def __init__(self,posCenter,size=[200,200]):\n        self.posCenter = posCenter\n        self.size = size\n\n    def updata(self,cursor):\n        cx,cy = self.posCenter\n        w,h = self.size\n\n        # conferir se o dedo esta em cima da imagem e move para a posição do dedo\n        if cx - w // 2 \u003c cursor[0] \u003c cx + w // 2 and cy - h // 2 \u003c cursor[1] \u003c cy + h // 2 :\n            self.posCenter = cursor\n```\n\n---\n\nCrio a lista `imgList` que vai guarda todas as imagens do quebra cabeça. Então finalmente pego a imagem completa do quebra-cabeça e divido em 5 partes iguais e as salvo, depois crio uma lista com 5 objetos `imgObject`. \n\n```python\nimgList = []\n\n#preparando a imagem para o quebra cabeça\nimagem = cv2.imread(\"test.jpg\")\nimagem1 = imagem[0:200,0:200]\nimagem2 = imagem[0:200,200:400]\nimagem3 = imagem[0:200,400:600]\nimagem4 = imagem[0:200,600:800]\nimagem5 = imagem[0:200,800:1000]\ncv2.imwrite(\"test3.jpg\",imagem1)\ncv2.imwrite(\"test4.jpg\",imagem2)\ncv2.imwrite(\"test1.jpg\",imagem3)\ncv2.imwrite(\"test2.jpg\",imagem4)\ncv2.imwrite(\"test0.jpg\",imagem5)\n\nfor x in range(5):\n    imgList.append(imgObject([x*250+150,150]))\n```\n\n---\n\nEssa linha em especifico é responsável por fazer a câmera virtual   \n\n```python\nwith pyvirtualcam.Camera(width=1280, height=720, fps=24, fmt=PixelFormat.BGR) as cam:\n```\n\n---\n\nAqui que começa propriamente dito o código. Começo então pegando a imagem da webcam e já começo desenhando a minha mão no vídeo. Logo após pega a posição dos dedos. Dentro do `if` confiro a distancia entre os dedos indicador e médio, se for menos que 40 então eles estão não posição de `click`, segura a imagem e logo depois confiro se estão dentro da imagem, se estiver então eu atualizo a posição da imagem para a do meu cursor. \n\n```python\nsuccess, img = cap.read()\n        img = detector.findHands(img)\n        lmList, _ = detector.findPosition(img) # posição da mão e dos dedos\n\n        if lmList:\n            l, _, _ = detector.findDistance(8,12,img,draw=False) # conta a distancia dos dedos\n\n            #conferir se os dedos estão juntos ou não (click)\n            if l \u003c 40 :\n                cursor = lmList[8] #posição do dedo indicador\n                # atualiza a posição\n                for rect in imgList:\n                    rect.updata(cursor)\n```\n\n---\n\nPor ultimo eu uso o `try` e `except`  para tentar plotar a imagem do quebra-cabeça na tela, usando os dados do `imgObject`, para isso uso o `imagem.copy()` \n\n```python\ntry:\n            #desenhar imagem na tela\n            for i, rect in enumerate(imgList):\n                filename = \"test%d.jpg\" % i\n                cx, cy = rect.posCenter\n                w, h = rect.size\n                imagem = cv2.imread(filename)\n                imagem = cv2.flip(imagem, 1)\n                img[cy-h//2:cy+h//2,cx-w//2:cx+w//2] = imagem.copy()\n\n                #parte verde do retangulo\n                cvzone.cornerRect(img,(cx-w//2,cy-h//2,w,h),20,rt=0)\n        except:\n            pass\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrankson18%2Fvirtual-puzzle-on-google-meet-with-python-and-opencv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrankson18%2Fvirtual-puzzle-on-google-meet-with-python-and-opencv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrankson18%2Fvirtual-puzzle-on-google-meet-with-python-and-opencv/lists"}