Aug-06-2024, 02:55 PM
I have written some code that takes screenshots of a dual-monitor setup. If it 'sees' images with a certain ratio of skin tone-colored pixels, if sends that image to an accountability partner. This was written to solve the problem of a porn addict on his work computer who does not have admin privileges and needed to be able to run something like a python script to help with accountability.
I am interested in any ways to improve the code because I am a novice when it comes to programming. Also, I am looking into ways to make the running of the code automatic and ways to keep from getting around it.
Currently, I have a .bat file that runs the python code at computer startup, but the trouble is that I haven't been able to get an automatic computer shutdown to occur when the user 'forgets' to shut down the machine.
I am interested in any ways to improve the code because I am a novice when it comes to programming. Also, I am looking into ways to make the running of the code automatic and ways to keep from getting around it.
Currently, I have a .bat file that runs the python code at computer startup, but the trouble is that I haven't been able to get an automatic computer shutdown to occur when the user 'forgets' to shut down the machine.
# This script takes a screenshot of both monitors and if a certain portion of the screen contains colors
# that have skin tones, then an email will go to an accountability partner.
import mss
import mss.tools
from datetime import datetime, timedelta
import time
import cv2
import matplotlib.pyplot as plt
import os #using
import numpy as np
import smtplib #using
from email.mime.text import MIMEText #using
from email.mime.multipart import MIMEMultipart #using
from email.mime.image import MIMEImage #using
# Function to send email with file names and images
# Arguments--Subject of email, message in text, email address to send to & image path
def send_email(subject, message, to_email, image_path):
# Gain access to email server
smtp_server = 'smtp.office365.com'
smtp_port = 587
smtp_username = 'username_goes_here'
smtp_password = 'password_here_please'
# Define variables for the email
msg = MIMEMultipart()
msg['From'] = smtp_username
msg['To'] = to_email
msg['Subject'] = subject
msg.attach(MIMEText(message, 'plain'))
if image_path:
print(f'Image path: {image_path}')
# os.path.isfile() method is used to check whether the specified path is an existing file or not
if os.path.isfile(image_path):
for img in skin_images:
image_path = os.path.join(image_folder, img)
with open(image_path, 'rb') as f:
img_data = f.read()
img_mime = MIMEImage(img_data, name=os.path.basename(image_path))
msg.attach(img_mime)
else:
print(f"Error: Image file '{image_path}' not found.")
try:
# Connect to Microsoft SMTP server
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls() # Secure the connection
server.login(smtp_username, smtp_password) # Login to email server
# Send email
server.sendmail(smtp_username, to_email, msg.as_string())
print(f"Accountability Email to SomeOtherDude sent successfully to {to_email}!")
server.quit() # Disconnect from server
except smtplib.SMTPAuthenticationError as e:
print(f"Failed to send email: SMTP Authentication Error - {e}")
except smtplib.SMTPException as e:
print(f"Failed to send email: SMTP Exception - {e}")
except Exception as e:
print(f"Failed to send email: {str(e)}")
# Function to detect skin tones in images
def detect_skin_tones(image_folder, skin_threshold_ratio=0.03):
skin_images = []
# Iterate through images in the folder
for filename in os.listdir(image_folder):
if filename.endswith(".jpg") or filename.endswith(".png"):
# Read image
img_path = os.path.join(image_folder, filename)
image = cv2.imread(img_path)
# Convert image from BGR to HSV
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# Define skin tone ranges in HSV color space
lower_skin = np.array([0, 48, 80], dtype=np.uint8)
upper_skin = np.array([20, 255, 255], dtype=np.uint8)
# Create mask for skin tones
mask = cv2.inRange(hsv_image, lower_skin, upper_skin)
# Count skin tone pixels
skin_pixel_count = cv2.countNonZero(mask)
# Calculate total number of pixels in the image
total_pixels = image.shape[0] * image.shape[1]
# Calculate skin tone threshold based on image size
skin_threshold = total_pixels * skin_threshold_ratio
# Check if skin pixels exceed threshold
if skin_pixel_count >= skin_threshold:
skin_images.append(filename)
return skin_images
def capture_and_save_screenshot(monitor_index, filename_prefix):
with mss.mss() as sct:
mon = sct.monitors[monitor_index]
monitor = {
"top": mon["top"],
"left": mon["left"],
"width": mon["width"],
"height": mon["height"],
"mon": monitor_index,
}
current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
output = f"{filename_prefix}_{current_time}.png"
sct_img = sct.grab(monitor)
image = mss.tools.to_png(sct_img.rgb, sct_img.size, output=output)
return output
# Testing snippet. Comment out the Working snippet before using. Also comment out email send.
#iteration_count = 0
#while iteration_count < 1:
# iteration_count += 1
# capture_and_save_screenshot(1, "Monitor_1")
# capture_and_save_screenshot(2, "Monitor_2")
# time.sleep(1)
# Working snippet. Un-comment out send email method call
iteration_count = 0
while iteration_count < 72:
iteration_count += 1
capture_and_save_screenshot(1, "Monitor_1")
capture_and_save_screenshot(2, "Monitor_2")
time.sleep(600)
image_folder = 'C:\\Users\\blahblah\\Desktop\\+Loc_Ref_Files\\Screenshots'
# skin_images is a list of file names that show skin tones
skin_images = detect_skin_tones(image_folder, skin_threshold_ratio=0.03)
#print(f'Skin images detected in image folder: {skin_images}')
# Comment out the section below if testing, but if testing email section then don't.
if skin_images:
subject = 'Accountability for SomeDude'
message = f'Ask SomeDude about these screenshots: {skin_images}'
message2 = 'No explicit images were found today. Yay!'
to_email = '[email protected]' # [email protected]
if skin_images:
image_path = os.path.join(image_folder, skin_images[0])
send_email(subject, message, to_email, image_path)
else:
send_email(subject, message2, to_email)
