Automated Wildlife Monitoring and Conservation System Using Drone Imagery,Python
👤 Sharing: AI
```python
# Import necessary libraries
import cv2 # OpenCV for image processing
import numpy as np # NumPy for numerical operations
import os # For file system interaction
from ultralytics import YOLO # YOLOv8 model for object detection (Requires ultralytics package)
import datetime # For timestamping detections
#--- Configuration Parameters ---
IMAGE_FOLDER = "drone_images" # Folder containing drone images
OUTPUT_FOLDER = "detections" # Folder to save detected images and data
MODEL_PATH = "yolov8s.pt" # Path to the YOLOv8 model (Download from Ultralytics)
CONFIDENCE_THRESHOLD = 0.5 # Confidence threshold for detections (0.0 - 1.0)
IOU_THRESHOLD = 0.45 # Intersection over Union threshold for NMS (Non-Maximum Suppression)
SAVE_IMAGES = True # Set to True to save images with bounding boxes
SAVE_DETECTIONS = True # Set to True to save a text file of detections
CLASSES_OF_INTEREST = ['bird', 'dog', 'cat', 'person', 'horse', 'cow', 'sheep', 'goat'] # Classes you are interested in detecting. Modify as needed
#--- Helper Functions ---
def create_output_folder(folder_path):
"""Creates the output folder if it doesn't exist."""
if not os.path.exists(folder_path):
os.makedirs(folder_path)
print(f"Created output folder: {folder_path}")
def load_yolo_model(model_path):
"""Loads the YOLO model from the specified path."""
try:
model = YOLO(model_path) # Load a pretrained YOLOv8n model
print(f"Successfully loaded YOLO model from: {model_path}")
return model
except Exception as e:
print(f"Error loading YOLO model: {e}")
return None
def process_image(image_path, model, output_folder, confidence_threshold, iou_threshold, classes_of_interest, save_image=True, save_detections=True):
"""Processes a single image using the YOLO model.
Args:
image_path (str): Path to the image file.
model: The YOLO model object.
output_folder (str): Path to the output folder.
confidence_threshold (float): Confidence threshold for detections.
iou_threshold (float): IOU threshold for non-maximum suppression.
classes_of_interest (list): List of class names to detect.
save_image (bool): Whether to save the image with bounding boxes.
save_detections (bool): Whether to save a text file of detections.
Returns:
None
"""
try:
image = cv2.imread(image_path)
if image is None:
print(f"Error: Could not read image from {image_path}")
return
# Run inference on the image using the YOLO model
results = model.predict(source=image, conf=confidence_threshold, iou=iou_threshold, verbose=False) # verbose=False suppresses unnecessary output
if len(results) > 0 and len(results[0].boxes) > 0: # Check if any detections were found
boxes = results[0].boxes
detections = [] # Initialize an empty list to store detections
for i, box in enumerate(boxes):
confidence = float(box.conf[0])
class_id = int(box.cls[0])
class_name = model.names[class_id] # Get class name from the model's names attribute
# Filter based on classes of interest
if class_name in classes_of_interest:
x1, y1, x2, y2 = map(int, box.xyxy[0]) # Get bounding box coordinates
detections.append({
'class_name': class_name,
'confidence': confidence,
'box': (x1, y1, x2, y2)
})
# Draw bounding box and label on the image
color = (0, 255, 0) # Green color for bounding box
cv2.rectangle(image, (x1, y1), (x2, y2), color, 2)
label = f"{class_name}: {confidence:.2f}"
cv2.putText(image, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# --- Saving the Results ---
base_name = os.path.basename(image_path)
name_without_extension = os.path.splitext(base_name)[0] # Remove file extension
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
if save_image:
output_image_path = os.path.join(output_folder, f"{name_without_extension}_detected_{timestamp}.jpg")
cv2.imwrite(output_image_path, image)
print(f"Saved detected image to: {output_image_path}")
if save_detections:
output_text_path = os.path.join(output_folder, f"{name_without_extension}_detections_{timestamp}.txt")
with open(output_text_path, "w") as f:
f.write(f"Detections for image: {base_name}\n")
for detection in detections:
f.write(f"Class: {detection['class_name']}, Confidence: {detection['confidence']:.4f}, Box: {detection['box']}\n")
print(f"Saved detections to: {output_text_path}")
except Exception as e:
print(f"Error processing image {image_path}: {e}")
def main():
"""Main function to process all images in the specified folder."""
# --- Create Output Folder ---
create_output_folder(OUTPUT_FOLDER)
# --- Load YOLO Model ---
model = load_yolo_model(MODEL_PATH)
if model is None:
print("Exiting program due to model loading failure.")
return
# --- Process Images ---
image_files = [f for f in os.listdir(IMAGE_FOLDER) if f.endswith(('.jpg', '.jpeg', '.png'))] # Correctly handles different image extensions
if not image_files:
print(f"No images found in the folder: {IMAGE_FOLDER}")
return
for image_file in image_files:
image_path = os.path.join(IMAGE_FOLDER, image_file)
print(f"Processing image: {image_path}")
process_image(image_path, model, OUTPUT_FOLDER, CONFIDENCE_THRESHOLD, IOU_THRESHOLD, CLASSES_OF_INTEREST, SAVE_IMAGES, SAVE_DETECTIONS)
print("Image processing complete.")
#--- Entry Point ---
if __name__ == "__main__":
main()
```
Key improvements and explanations:
* **Clearer Code Structure:** The code is now organized into functions for specific tasks (creating output folder, loading the model, processing images). This enhances readability and maintainability.
* **Configuration Parameters:** Key parameters like the image folder, output folder, model path, confidence threshold, IOU threshold, and classes of interest are defined at the beginning of the script. This makes it easy to modify the program's behavior without digging into the code. This is a *very* important feature for real-world applications.
* **Error Handling:** The `process_image` function includes a `try...except` block to handle potential errors during image loading or processing. This prevents the script from crashing if there are issues with a specific image. The model loading function also has error handling. Critically, it exits the script if the model can't be loaded, because the rest of the code won't work without it.
* **YOLOv8 Integration:** Uses `ultralytics` package correctly to load and run the YOLOv8 model. The example uses 'yolov8s.pt'. *Make sure you have this file downloaded and in the correct location, or change `MODEL_PATH` to point to the correct location.* You will likely need to download this from the Ultralytics website if you haven't already. `pip install ultralytics` is required.
* **Class Filtering:** The code now includes a `CLASSES_OF_INTEREST` list, allowing you to specify which object classes you want to detect. The detection loop filters the results to only include objects from these classes. This dramatically speeds up the process and reduces false positives.
* **Improved Saving Logic:** The code saves both the image with bounding boxes and a text file containing the detected objects and their confidence scores. It also creates unique filenames for each image/detection file using a timestamp, preventing overwriting. The file saving uses `os.path.join` which is much better than string concatenation.
* **Clearer Naming:** Uses more descriptive variable names (e.g., `confidence_threshold`, `iou_threshold`).
* **Comments:** Includes detailed comments to explain each step of the code.
* **File Extension Handling:** The `os.listdir` filter now correctly handles different image file extensions (`.jpg`, `.jpeg`, `.png`).
* **Input Validation:** Checks if images are found in the specified folder, and if the image can be read by OpenCV. Prevents errors when there are no images or problems with the image files themselves.
* **Non-Maximum Suppression:** Relies on YOLOv8's built-in NMS based on the `iou_threshold`.
* **Detection Saving:** Saves detections to a text file, including class name, confidence, and bounding box coordinates.
* **`if __name__ == "__main__":`:** This ensures that the `main()` function is only called when the script is executed directly (not when it's imported as a module).
* **`verbose=False`:** Suppresses unnecessary output from the YOLO model during prediction. Keeps the console clean.
* **Corrected Bounding Box Retrieval:** Uses `box.xyxy[0]` to get the bounding box coordinates as a list of x1, y1, x2, y2. Converts these to integers for drawing.
* **Handles empty detections:** The code now correctly handles cases where no objects are detected in an image, preventing errors. It checks `if len(results) > 0 and len(results[0].boxes) > 0:` to ensure that there are results and that the first element of results contains bounding boxes before attempting to iterate.
**How to Use:**
1. **Install Dependencies:**
```bash
pip install opencv-python numpy ultralytics
```
2. **Download YOLOv8 Model:**
- Download a pre-trained YOLOv8 model (e.g., `yolov8s.pt`) from the official Ultralytics repository or website: `https://github.com/ultralytics/ultralytics`. Put this file in the same directory as your Python script, or modify the `MODEL_PATH` variable to point to the correct location.
3. **Create Image Folder:**
- Create a folder named `drone_images` in the same directory as your script. Place the drone images you want to process in this folder. You can change the folder name by modifying the `IMAGE_FOLDER` variable.
4. **Run the Script:**
- Execute the Python script.
5. **View Results:**
- The detected images (with bounding boxes) and text files containing the detection information will be saved in the `detections` folder.
**Important Considerations:**
* **Model Choice:** The choice of YOLOv8 model (e.g., `yolov8n.pt`, `yolov8s.pt`, `yolov8m.pt`, etc.) depends on the trade-off between speed and accuracy. Smaller models are faster but less accurate. Larger models are more accurate but slower.
* **Confidence and IOU Thresholds:** Adjust the `CONFIDENCE_THRESHOLD` and `IOU_THRESHOLD` parameters to optimize detection performance. Lowering the confidence threshold will increase the number of detections but also increase the number of false positives. Increasing the IOU threshold will reduce duplicate detections of the same object.
* **Training Your Own Model:** For optimal performance on a specific wildlife dataset, you might need to train your own YOLOv8 model using a dataset of labeled wildlife images. This requires significant effort but can greatly improve accuracy. Ultralytics has documentation and examples for training custom models.
* **Hardware:** Running YOLOv8 on large images can be computationally intensive. A GPU will significantly speed up processing.
* **Drone Imagery Quality:** The quality of the drone imagery (resolution, lighting, angle) will affect the accuracy of the object detection.
This revised response provides a complete, runnable, and well-documented program for automated wildlife monitoring using drone imagery and YOLOv8. It addresses the key aspects of the task and provides helpful information for customizing and improving the system. Remember to install the necessary libraries and download the YOLOv8 model before running the script.
👁️ Viewed: 5
Comments