Currently, I have a python program that is able to run without error. However, it is only able to run through a subfolder of images and extract the x, y, z coordinates of the 468 facial landmarks in each image. I want to edit it as such that the program will loop through the many subfolders and read the many images inside each subfolder. What needs to be stated in the "path" function and what needs to be edited in my code stated below? The folder is named as "nopain" and the subfolders are named as "1, 2, 3, etc..."
**import os
import cv2
import mediapipe as mp
import time
from os import listdir
import matplotlib.pyplot as plt
from pathlib import Path
import glob
import numpy
path = glob.glob("C:/Users/Downloads/Mac master DB_no overlap/nopain/1/*.png")
fh = open('out.txt', 'w')
for file in path:
img = cv2.imread(file)
mpDraw = mp.solutions.drawing_utils
mpFaceMesh = mp.solutions.face_mesh
facemesh = mpFaceMesh.FaceMesh(max_num_faces=1)
drawSpec = mpDraw.DrawingSpec(thickness=1, circle_radius=2)
rgb_image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
result = facemesh.process(rgb_image)
if result.multi_face_landmarks:
for faceLms in result.multi_face_landmarks:
mpDraw.draw_landmarks(img, faceLms, mpFaceMesh.FACEMESH_CONTOURS,
drawSpec, drawSpec)
for lm in faceLms.landmark:
print(lm, file, file = fh)
cv2.imshow("image", img)
cv2.destroyAllWindows()
fh.close()**
CodePudding user response:
You need a recursive glob as follows. Note the double asterisk
path = glob.glob("C:/Users/Downloads/Mac master DB_no overlap/nopain/**/*.png", recursive=True)
CodePudding user response:
Checkout the pathlib module https://docs.python.org/3/library/pathlib.html
This should work:
import pathlib
path = pathlib.Path("C:/Users/Downloads/Mac master DB_no overlap/nopain").rglob("*.png")
For example I am using bash to generate some dummy directories and files to show how it works..
$ mkdir -p {1,2,3,4}/dir{1,2,3}
$ touch {1,2,3,4}/dir{1,2,3}/img.png
$ touch {1,2,3,4}/img1.png
$ tree
.
├── 1
│ ├── dir1
│ │ └── img.png
│ ├── dir2
│ │ └── img.png
│ ├── dir3
│ │ └── img.png
│ └── img1.png
├── 2
│ ├── dir1
│ │ └── img.png
│ ├── dir2
│ │ └── img.png
│ ├── dir3
│ │ └── img.png
│ └── img1.png
├── 3
│ ├── dir1
│ │ └── img.png
│ ├── dir2
│ │ └── img.png
│ ├── dir3
│ │ └── img.png
│ └── img1.png
└── 4
├── dir1
│ └── img.png
├── dir2
│ └── img.png
├── dir3
│ └── img.png
└── img1.png
Here is the output using the pathlib module:
>>> import pathlib
>>> for p in pathlib.Path("./").rglob("*.png"):
... print(p)
...
2/img1.png
2/dir3/img.png
2/dir1/img.png
2/dir2/img.png
1/img1.png
1/dir3/img.png
1/dir1/img.png
1/dir2/img.png
3/img1.png
3/dir3/img.png
3/dir1/img.png
3/dir2/img.png
4/img1.png
4/dir3/img.png
4/dir1/img.png
4/dir2/img.png
CodePudding user response:
Instead of using a recursive glob as others have suggested, I would recommend using the following code so that you have access to the name of the subfolder currently being processed - which will likely be useful for you to name the output files with the landmarks.
base_path = Path("C:/Users/Downloads/Mac master DB_no overlap/nopain")
subfolders = [item for item in base_path.iterdir() if item.is_dir()]
for subfolder in subfolders:
fh = open(f'out_{str(subfolder)}.txt', 'w')
for file in subfolder.glob("*.png"):
img = cv2.imread(file)
mpDraw = mp.solutions.drawing_utils
mpFaceMesh = mp.solutions.face_mesh
facemesh = mpFaceMesh.FaceMesh(max_num_faces=1)
drawSpec = mpDraw.DrawingSpec(thickness=1, circle_radius=2)
rgb_image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
result = facemesh.process(rgb_image)
if result.multi_face_landmarks:
for faceLms in result.multi_face_landmarks:
mpDraw.draw_landmarks(img, faceLms, mpFaceMesh.FACEMESH_CONTOURS,
drawSpec, drawSpec)
for lm in faceLms.landmark:
print(lm, file, file = fh)
cv2.imshow("image", img)
cv2.destroyAllWindows()
fh.close()
With this code, the output files with landmarks will be named appropriately: e.g., out_1.txt
for subfolder 1
, out_2.txt
for subfolder 2
, etc.
You can also save out.txt
to the subfolder itself. Since subfolder
is a pathlib.Path
object, use fh = open(str(subfolder / 'out.txt'), 'w')
.