Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .clangd
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# yaml-language-server: $schema=https://json.schemastore.org/clangd.json

CompileFlags:
CompilationDatabase: "build/"

Add:
- "-std=c++17"
- "-IC:/libraries/opencv/build/include"
Expand Down
File renamed without changes.
Binary file added input/asian1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added input/my_face.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added input/some_crying_girl.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_cropped/asian1_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_cropped/example (1)_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_cropped/example (2)_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_cropped/example (3)_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_cropped/my_face_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_cropped/some_crying_girl_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_debug/asian1_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_debug/example (1)_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_debug/example (2)_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_debug/example (3)_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_debug/my_face_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/face_debug/some_crying_girl_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_cropped/asian1_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_cropped/example (1)_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_cropped/example (2)_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_cropped/example (3)_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_cropped/my_face_face_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_debug/asian1_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_debug/example (1)_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_debug/example (2)_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_debug/example (3)_face_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/fullbody_debug/my_face_face_0.jpg
Binary file added output/fullbody_debug/some_crying_girl_face_0.jpg
Binary file added output/upperbody_cropped/asian1_face_0.png
Binary file modified output/upperbody_cropped/example (1)_face_0.png
Binary file modified output/upperbody_cropped/example (2)_face_0.png
Binary file modified output/upperbody_cropped/example (3)_face_0.png
Binary file added output/upperbody_cropped/my_face_face_0.png
Binary file added output/upperbody_debug/asian1_face_0.jpg
Binary file added output/upperbody_debug/my_face_face_0.jpg
1 change: 1 addition & 0 deletions src/crop_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum class CropType {

struct CropConfig
{
std::string input_folder;
std::string error_folder;
std::string debug_folder;
std::string output_folder;
Expand Down
368 changes: 368 additions & 0 deletions src/image_processing.cpp

Large diffs are not rendered by default.

32 changes: 29 additions & 3 deletions src/image_processing.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include<string>
#include <opencv2/opencv.hpp>
#include <string>
#include "crop_config.h"
#include "user_input.h"

Expand All @@ -14,13 +14,39 @@ struct ImageProcessConfig {
int min_fullbody_res;
};

void images_error(
void link_image_error(
const std::string& image_path,
const std::string& error_folder
);

int process_image(
const std::string& image_path,
const CropConfig& crop,
const ImageProcessConfig& process_config,
const PreviewConfig& preview_config
);

bool draw_rectangle(
const int& endX,
const int& startX,
const int& endY,
const int& startY,
cv::Mat& image,
const std::string& image_path,
const std::string& filename,
const CropConfig& crop,
const ImageProcessConfig& process_config,
const PreviewConfig& preview_config,
bool is_error,
int face_index,
float confidence,
const std::string& error_msg
);

void preview(
const cv::Mat& debug_image,
const cv::Mat& resized_image,
const int& preview_output_res,
const int& preview_debug_max_res,
bool is_error
);
164 changes: 162 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,169 @@
#include <opencv2/opencv.hpp>
#include <nlohmann/json.hpp>

#include "crop_config.h"
#include "image_processing.h"
#include "user_input.h"

#include <fstream>
#include <string>
#include <atomic>
#include <future>
#include <thread>
#include <vector>
#include <filesystem>

#define DEFAULT_OUTPUT_FOLDER "output_folder"
#define DEFAULT_DEBUG_FOLDER "debug_folder"
#define DEFAULT_ERROR_FOLDER "error_folder"

// I have no ideas, what I'm doing

using json = nlohmann::json;
namespace fs = std::filesystem;

void processMultithread(const CropConfig& crop,
const ImageProcessConfig& process_config,
const PreviewConfig& preview_config)
{
clean_output(crop.output_folder, crop.debug_folder, crop.error_folder);

// Collect input files
std::vector<fs::path> inputFiles;
for (const auto& entry : fs::directory_iterator(crop.input_folder))
if (entry.is_regular_file())
inputFiles.push_back(entry.path());

std::atomic<int> errorCount{0};
std::vector<std::future<int>> futures;

// Launch async tasks
for (const auto& file : inputFiles)
{
futures.push_back(std::async(std::launch::async, [file, &crop, &process_config, &preview_config]()
{
return process_image(file.string(), crop, process_config, preview_config);
}));
}

// Wait and collect results
int processed = 0;
for (auto& f : futures)
{
errorCount += f.get();
processed++;
std::cout << "\rProcessing: " << processed << "/" << inputFiles.size() << std::flush;
}

cv::destroyAllWindows();

int totalOutputImages = 0;
for (const auto& entry : fs::directory_iterator(crop.output_folder))
if (entry.is_regular_file())
totalOutputImages++;

std::cout << "\nTotal images: " << inputFiles.size() << "\n"
<< "Processed images: " << inputFiles.size() - errorCount << "\n"
<< "Total faces detected: " << totalOutputImages << "\n"
<< "Error images: " << errorCount << "\n";
}

int main()
{
std::ifstream config("config.json");
return 0;
try
{
std::ifstream f("config.json");
if (!f)
{
std::cerr<< "config.json does not exist, please put config.json at where your executable are" << std::endl;
return 1;
}
json JSON_config = json::parse(f);

// Load config
ImageProcessConfig process_config;
process_config.output_res = JSON_config.value("output_res", 1080);
process_config.preview_output_res = JSON_config.value("preview_output_res", 256);
process_config.preview_debug_max_res = JSON_config.value("preview_debug_max_res", 640);
process_config.confidence_level = JSON_config.value("confidence_level", 0.5f);
process_config.min_face_res = JSON_config.value("min_face_res", 96);
process_config.min_upperbody_res = JSON_config.value("min_upperbody_res", 64);
process_config.min_fullbody_res = JSON_config.value("min_fullbody_res", 32);

CropConfig crop;
crop.input_folder = JSON_config.value("input_folder", "input");
crop.output_folder = JSON_config.value("output_upperbody_folder", DEFAULT_OUTPUT_FOLDER);
crop.debug_folder = JSON_config.value("debug_upperbody_folder", DEFAULT_DEBUG_FOLDER);
crop.error_folder = JSON_config.value("error_folder", DEFAULT_ERROR_FOLDER);

// Get user input
CropConfig crop_selection = select_option();
crop.crop_type = crop_selection.crop_type;
crop.top_margin = crop_selection.top_margin;
crop.bottom_margin = crop_selection.bottom_margin;

// Set output folders based on crop type
switch (crop.crop_type)
{
case CropType::UpperBody:
crop.output_folder = JSON_config.value("output_upperbody_folder", DEFAULT_OUTPUT_FOLDER);
crop.debug_folder = JSON_config.value("debug_upperbody_folder", DEFAULT_DEBUG_FOLDER);
break;
case CropType::Face:
crop.output_folder = JSON_config.value("output_face_folder", DEFAULT_OUTPUT_FOLDER);
crop.debug_folder = JSON_config.value("debug_face_folder", DEFAULT_DEBUG_FOLDER);
break;
case CropType::FullBody:
crop.output_folder = JSON_config.value("output_fullbody_folder", DEFAULT_OUTPUT_FOLDER);
crop.debug_folder = JSON_config.value("debug_fullbody_folder", DEFAULT_DEBUG_FOLDER);
break;
}

fs::create_directories(crop.input_folder);

PreviewConfig preview_config = preview_window();

if (preview_config.parallel)
{
processMultithread(crop, process_config, preview_config);
}
else
{
// Singlethread mode
clean_output(crop.output_folder, crop.debug_folder, crop.error_folder);

std::vector<fs::path> inputFiles;
for (const auto& entry : fs::directory_iterator(crop.input_folder))
if (entry.is_regular_file())
inputFiles.push_back(entry.path());

int errorCount = 0;
int processed = 0;
for (const auto& file : inputFiles)
{
errorCount += process_image(file.string(), crop, process_config, preview_config);
processed++;
std::cout << "\rProcessing: " << processed << "/" << inputFiles.size() << std::flush;
}

cv::destroyAllWindows();

int totalOutputImages = 0;
for (const auto& entry : fs::directory_iterator(crop.output_folder))
if (entry.is_regular_file())
totalOutputImages++;

std::cout << "\nTotal images: " << inputFiles.size() << "\n"
<< "Processed images: " << inputFiles.size() - errorCount << "\n"
<< "Total faces detected: " << totalOutputImages << "\n"
<< "Error images: " << errorCount << "\n";
}

return 0;
}
catch (const std::exception& e)
{
std::cerr << "Error: " << e.what() << "\n";
return 1;
}
}
3 changes: 3 additions & 0 deletions src/user_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ void delete_files(const std::string& folder) {
void clean_output(const std::string& output_folder,
const std::string& debug_output,
const std::string& error_folder) {
fs::create_directories(output_folder);
fs::create_directories(debug_output);
fs::create_directories(error_folder);

while (!fs::is_empty(output_folder)) {
char input;
Expand Down
Loading