Complete Tutorial: LabelMe with Login System and Dataset Management
This guide provides step-by-step instructions for setting up LabelMe with a custom login system and proper dataset management. We'll cover the entire workflow: login → annotation → save → logout.
System Overview
We'll build a system with the following components:
- LabelMe running in a Docker container with a configured dataset folder
- PHP-based authentication system
- Web server (Apache) to host the login portal
- Dataset management structure
Prerequisites
- A Linux server (Ubuntu 20.04 LTS or newer recommended)
- Root or sudo access to the server
- Docker and Docker Compose installed
- Apache web server with PHP support
Part 1: Server Preparation
Step 1: Update System and Install Required Packages
# Update package lists
sudo apt update
sudo apt upgrade -y
# Install necessary packages
sudo apt install -y docker.io docker-compose apache2 php libapache2-mod-php php-json
sudo systemctl enable docker
sudo systemctl start docker
# Add your user to docker group to avoid using sudo with docker commands
sudo usermod -aG docker $USER
# Log out and log back in for this to take effect
Step 2: Create Project Directory Structure
# Create main project directory
mkdir -p ~/labelme-project
cd ~/labelme-project
# Create directories for different components
mkdir -p docker-labelme
mkdir -p web-portal
mkdir -p datasets/{project1,project2}
mkdir -p annotations
# Add some sample images to project1 (optional)
# You can replace this with your own dataset copying commands
mkdir -p datasets/project1/images
# Copy some sample images if you have them
# cp /path/to/your/images/*.jpg datasets/project1/images/
Part 2: Set Up LabelMe Docker Container
Step 1: Create Docker Compose Configuration
Create a file docker-labelme/docker-compose.yml
:
cd ~/labelme-project/docker-labelme
nano docker-compose.yml
Add the following content:
version: '3'
services:
labelme:
image: wkentaro/labelme
container_name: labelme-server
ports:
- "8080:8080"
volumes:
- ../datasets:/data
- ../annotations:/home/developer/.labelmerc
environment:
- LABELME_SERVER=1
- LABELME_PORT=8080
- LABELME_HOST=0.0.0.0
command: labelme --server --port 8080 --host 0.0.0.0 /data
restart: unless-stopped
Step 2: Create LabelMe Configuration File
This step ensures annotations are saved in the proper format and location:
cd ~/labelme-project
nano annotations/.labelmerc
Add the following content:
{
"auto_save": true,
"display_label_popup": true,
"store_data": true,
"keep_prev": false,
"flags": null,
"flags_2": null,
"flags_3": null,
"label_flags": null,
"labels": ["person", "car", "bicycle", "dog", "cat", "tree", "building"],
"file_search": true,
"show_label_text": true
}
Customize the labels
list according to your annotation needs.
Step 3: Start LabelMe Container
cd ~/labelme-project/docker-labelme
docker-compose up -d
Verify it's running:
docker ps
You should see the labelme-server container running and listening on port 8080.
Part 3: Set Up Web Portal with Login System
Step 1: Create the Login Page
cd ~/labelme-project/web-portal
nano index.php
Add the following content:
<?php
// Display errors during development (remove in production)
ini_set('display_errors', 1);
error_reporting(E_ALL);
// Start session
session_start();
// Check if there's an error message
$error_message = isset($_SESSION['error_message']) ? $_SESSION['error_message'] : '';
// Clear error message after displaying it
unset($_SESSION['error_message']);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LabelMe Login</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.login-container {
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
width: 350px;
}
h2 {
text-align: center;
color: #333;
margin-bottom: 20px;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 12px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
border-radius: 4px;
}
button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 10px 0;
border: none;
cursor: pointer;
width: 100%;
border-radius: 4px;
font-size: 16px;
}
button:hover {
opacity: 0.8;
}
.error-message {
color: #f44336;
text-align: center;
margin-top: 10px;
}
.logo {
text-align: center;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="login-container">
<div class="logo">
<h2>LabelMe Annotation</h2>
</div>
<form id="loginForm" action="auth.php" method="post">
<div>
<label for="username"><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="username" required>
</div>
<div>
<label for="password"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="password" required>
</div>
<div>
<label for="project"><b>Select Project</b></label>
<select name="project" style="width: 100%; padding: 12px; margin: 8px 0; display: inline-block; border: 1px solid #ccc; box-sizing: border-box; border-radius: 4px;">
<option value="project1">Project 1</option>
<option value="project2">Project 2</option>
</select>
</div>
<button type="submit">Login</button>
<?php if (!empty($error_message)): ?>
<div class="error-message"><?php echo htmlspecialchars($error_message); ?></div>
<?php endif; ?>
</form>
</div>
</body>
</html>
Step 2: Create the Authentication Script
cd ~/labelme-project/web-portal
nano auth.php
Add the following content:
<?php
// Start session management
session_start();
// Display errors during development (remove in production)
ini_set('display_errors', 1);
error_reporting(E_ALL);
// Configuration - Store these securely in production
$users = [
'admin' => [
'password' => password_hash('admin123', PASSWORD_DEFAULT), // Use hashed passwords
'role' => 'admin'
],
'user1' => [
'password' => password_hash('user123', PASSWORD_DEFAULT),
'role' => 'annotator'
],
'user2' => [
'password' => password_hash('user456', PASSWORD_DEFAULT),
'role' => 'annotator'
]
];
// Base path to the LabelMe application
$labelme_base_url = 'http://localhost:8080'; // Change this to your LabelMe server address
// Handle login form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = isset($_POST['username']) ? $_POST['username'] : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
$project = isset($_POST['project']) ? $_POST['project'] : 'project1';
// Validate credentials
if (isset($users[$username]) && password_verify($password, $users[$username]['password'])) {
// Set session variables
$_SESSION['logged_in'] = true;
$_SESSION['username'] = $username;
$_SESSION['role'] = $users[$username]['role'];
$_SESSION['project'] = $project;
$_SESSION['last_activity'] = time();
// Redirect to LabelMe
header("Location: labelme.php");
exit;
} else {
// Failed login
$_SESSION['error_message'] = "Invalid username or password";
header("Location: index.php");
exit;
}
}
// For logout
if (isset($_GET['logout'])) {
// Log this logout
$log_file = 'user_activity.log';
$log_message = date('Y-m-d H:i:s') . " - User: " . ($_SESSION['username'] ?? 'unknown') .
" - Action: Logged out\n";
file_put_contents($log_file, $log_message, FILE_APPEND);
// Clear session data
session_unset();
session_destroy();
// Redirect to login page
header("Location: index.php");
exit;
}
?>
Step 3: Create the LabelMe Proxy Page
cd ~/labelme-project/web-portal
nano labelme.php
Add the following content:
<?php
// Start session management
session_start();
// Display errors during development (remove in production)
ini_set('display_errors', 1);
error_reporting(E_ALL);
// Check if user is logged in
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
// Not logged in, redirect to login page
header("Location: index.php");
exit;
}
// Security: Check for session timeout (30 minutes)
$timeout = 30 * 60; // 30 minutes in seconds
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $timeout)) {
// Session has expired
session_unset();
session_destroy();
header("Location: index.php?timeout=1");
exit;
}
// Update last activity time
$_SESSION['last_activity'] = time();
// Configuration
$labelme_base_url = 'http://localhost:8080'; // Change this to your LabelMe server address
$project = $_SESSION['project'] ?? 'project1';
$labelme_url = $labelme_base_url . '/' . $project;
// Log user activity
$log_file = 'user_activity.log';
$log_message = date('Y-m-d H:i:s') . " - User: " . $_SESSION['username'] .
" - Role: " . $_SESSION['role'] .
" - Project: " . $project .
" - Action: Accessed LabelMe\n";
file_put_contents($log_file, $log_message, FILE_APPEND);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LabelMe Annotation Tool</title>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
.header {
background-color: #333;
color: white;
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.user-info {
font-size: 14px;
}
.logout-btn {
background-color: #f44336;
color: white;
border: none;
padding: 5px 10px;
cursor: pointer;
border-radius: 3px;
text-decoration: none;
margin-left: 10px;
}
.logout-btn:hover {
background-color: #d32f2f;
}
.project-selector {
margin-left: 20px;
}
iframe {
width: 100%;
height: calc(100% - 50px);
border: none;
}
</style>
</head>
<body>
<div class="header">
<div>
<h3 style="margin:0;">LabelMe Annotation Tool</h3>
<span>Project: <strong><?php echo htmlspecialchars($project); ?></strong></span>
</div>
<div class="user-info">
Logged in as: <strong><?php echo htmlspecialchars($_SESSION['username']); ?></strong>
(<?php echo htmlspecialchars($_SESSION['role']); ?>)
<form method="post" action="" style="display:inline-block">
<select name="project" class="project-selector" onchange="this.form.submit()">
<option value="project1" <?php echo $project == 'project1' ? 'selected' : ''; ?>>Project 1</option>
<option value="project2" <?php echo $project == 'project2' ? 'selected' : ''; ?>>Project 2</option>
</select>
</form>
<a href="auth.php?logout=1" class="logout-btn">Logout</a>
</div>
</div>
<iframe src="<?php echo $labelme_url; ?>" allow="fullscreen"></iframe>
</body>
</html>
<?php
// Handle project switching
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['project'])) {
$newProject = $_POST['project'];
$_SESSION['project'] = $newProject;
// Log project switch
$log_message = date('Y-m-d H:i:s') . " - User: " . $_SESSION['username'] .
" - Action: Switched to project " . $newProject . "\n";
file_put_contents($log_file, $log_message, FILE_APPEND);
// Redirect to refresh the page with new project
header("Location: labelme.php");
exit;
}
?>
Step 4: Setup Apache Virtual Host
sudo nano /etc/apache2/sites-available/labelme-portal.conf
Add the following configuration:
<VirtualHost *:80>
ServerName labelme.yourdomain.com # Change this to your domain or IP
DocumentRoot /home/username/labelme-project/web-portal # Update with your actual path
<Directory /home/username/labelme-project/web-portal> # Update with your actual path
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/labelme-error.log
CustomLog ${APACHE_LOG_DIR}/labelme-access.log combined
</VirtualHost>
Update the paths to match your actual user and directory structure.
Step 5: Enable the Site and Restart Apache
sudo a2ensite labelme-portal.conf
sudo systemctl restart apache2
Step 6: Set Proper Permissions
# Set appropriate permissions for the web files
cd ~/labelme-project
sudo chown -R www-data:www-data web-portal
sudo chmod -R 755 web-portal
# Ensure the annotation directory is writable
sudo chown -R www-data:www-data annotations
sudo chmod -R 777 annotations
# Ensure datasets are accessible
sudo chmod -R 755 datasets
Part 4: Dataset Management
Step 1: Organize Your Datasets
Structure your dataset directories as follows:
datasets/
├── project1/
│ ├── images/
│ │ ├── image1.jpg
│ │ ├── image2.jpg
│ │ └── ...
│ └── annotations/ # LabelMe will save annotations here
├── project2/
│ ├── images/
│ │ ├── image1.jpg
│ │ └── ...
│ └── annotations/
└── ...
Step 2: Add Scripts for Managing Datasets (Optional)
Create a script to add new projects:
cd ~/labelme-project
nano add-project.sh
Add the following content:
#!/bin/bash
# Script to add a new project to the LabelMe setup
# Check if a project name was provided
if [ -z "$1" ]; then
echo "Usage: $0 <project_name>"
exit 1
fi
PROJECT_NAME="$1"
PROJECT_DIR="$HOME/labelme-project/datasets/$PROJECT_NAME"
# Create project directory structure
mkdir -p "$PROJECT_DIR/images"
mkdir -p "$PROJECT_DIR/annotations"
# Set permissions
chmod -R 755 "$PROJECT_DIR"
# Update the web portal to include the new project
# (This is a simplified approach - you'll need to manually edit index.php and labelme.php)
echo "Project directory created at: $PROJECT_DIR"
echo "Now copy your images to: $PROJECT_DIR/images/"
echo "Remember to manually update index.php and labelme.php to include the new project"
Make the script executable:
chmod +x add-project.sh
Part 5: Testing the Complete System
Step 1: Access the Web Portal
Open your browser and navigate to:
http://your-server-ip/
orhttp://labelme.yourdomain.com/
Step 2: Login and Test the Workflow
- Log in with the credentials (e.g., username: admin, password: admin123)
- Select a project from the dropdown
- After login, you should see the LabelMe interface embedded in the page
- Test annotating an image:
- Click on an image
- Draw polygons/shapes around objects
- Enter labels for the objects
- Annotations are auto-saved to the corresponding project folder
- Try switching projects using the dropdown in the header
- Log out and verify you're redirected to the login page
Part 6: Security Enhancements (for Production)
Enable HTTPS
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d labelme.yourdomain.com
Improve Password Security
Edit the auth.php
file to use a database instead of hardcoded users.
Troubleshooting
LabelMe Not Loading
If LabelMe doesn't load in the iframe:
- Check if LabelMe is running:
docker ps
- Make sure port 8080 is accessible
- Check the Docker container logs:
docker logs labelme-server
Permission Issues
If you encounter permission issues with annotations:
sudo chmod -R 777 ~/labelme-project/annotations
sudo chown -R www-data:www-data ~/labelme-project/datasets
Annotation not Saving
If annotations aren't saving properly:
- Check the
.labelmerc
configuration file - Verify the permissions on the annotations directory
- Check for error messages in the Apache logs:
sudo tail -f /var/log/apache2/error.log
Conclusion
You now have a complete LabelMe annotation system with:
- Secure login/authentication
- Project selection
- Dataset organization
- User activity logging
- Session management
This setup allows your team to collaborate on annotation projects while maintaining control over who can access the system and what projects they can work on.