Initial Autocropper Steps

First steps towards implementing the autocropper.
Current plan is to use OpenCV in C++.
There are remains of testing to use stb image manipulation
but reading them in disregarded image orientation (ie it would
rotate on it's own) which is unacceptable.

Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
This commit is contained in:
Ethan Wellenreiter 2023-09-08 23:12:51 -04:00
parent e7b447208c
commit bf2fa97abe
11 changed files with 12631 additions and 0 deletions

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.22)
project(autocropper
VERSION 0.1
DESCRIPTION "Autocrops Receipt Pictures"
LANGUAGES CXX)
#GLOBING
file(GLOB_RECURSE SOURCE_FILES src/*.cpp)
add_executable(CropperEx main.cpp ${SOURCE_FILES})
# add_executable(CropperEx main.cpp
# src/dog.cpp
# src/operations.cpp)
target_compile_features(CropperEx PRIVATE cxx_std_20)
find_package(OpenCV REQUIRED)
target_link_libraries(CropperEx ${OpenCV_LIBS})
target_include_directories(CropperEx
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../externallibraries/stbimagehelpers
PRIVATE ${OpenCV_INCLUDE_DIRS})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

View File

@ -0,0 +1,14 @@
#ifndef CROPPER_H
#define CROPPER_H
#include "image.h"
class Cropper {
private:
Image picture;
};
#endif //CROPPER_H

View File

@ -0,0 +1,38 @@
#ifndef IMAGE_H
#define IMAGE_H
#include <stdint.h>
#include <cstdlib>
enum ImageType {
PNG,
JPG,
BMP,
TGA
};
class Image {
private:
uint8_t* data = NULL;
size_t size = 0;
int w;
int h;
int channels;
public:
Image(const char* filename);
Image(int w, int h, int channels);
Image(const Image& img);
~Image();
int const getWidth();
int const getChannels();
void setPixel(int pixelindex, int value);
bool read(const char* filename);
bool write(const char* filename);
ImageType getFileType(const char* filename);
};
#endif

View File

@ -0,0 +1 @@
#define DEBUG 1

98
code/autocropper/main.cpp Normal file
View File

@ -0,0 +1,98 @@
// #include <iostream>
// #include <string>
// #include <stdio.h>
// using namespace std;
// int main() {
// cout << "Hello World!!" << endl;
// }
#include <iostream>
// #include "image.h"
// #include <opencv2/opencv.hpp>
#include <opencv2/opencv.hpp>
// int main() {
// // Image test("../IMG_7594.png");
// // test.write("new.png");
// // Image copy = test;
// // int copyw = copy.getWidth();
// // int copychannels = copy.getChannels();
// // for (int i = 0; i < copyw * copychannels; i++) {
// // copy.setPixel(i, 255);
// // }
// // copy.write("copy.png");
// // Image blank(100, 100, 3);
// // blank.write("blank.jpg");
// cv::Mat image = cv::imread("../IMG_7594.png", cv::IMREAD_COLOR);
// if (image.empty()) {
// cout << "Could not read image" << endl;
// }
// Mat kernel1 = (Mat_<double>(3,3) << 0, 0, 0, 0, 1, 0, 0, 0, 0);
// int h, w;
// cv::imwrite("new.png", image);
// return 0;
// }
using namespace cv;
Mat src, lab;
Mat dst, detected_edges;
// int lowThreshold = 0;
// const int max_lowThreshold = 100;
const int ratio = 3;
const int kernel_size = 3;
const char* window_name = "Edge Map";
static void CannyThreshold(int, void*) {
std::cerr << "got here" << std::endl;
GaussianBlur(src, detected_edges, Size(3, 3), 0, 0);
std::cerr << "passed" << std::endl;
// Canny(detected_edges, detected_edges, lowThreshold, lowThreshold * ratio, kernel_size);
Mat sobelx, sobely, sobelxy;
Sobel(detected_edges, sobelx, CV_64F, 1, 0, 5);
std::cerr << "1" << std::endl;
Sobel(detected_edges, sobely, CV_64F, 0, 1, 5);
std::cerr << "2" << std::endl;
Sobel(detected_edges, sobelxy, CV_64F, 1, 1, 5);
std::cerr << "3" << std::endl;
// dst = Scalar::all(0);
// src.copyTo(dst, sobelxy);
imwrite("new.png", sobelxy);
// imshow(window_name, dst);
}
int main(int argc, char** argv) {
// CommandLineParser parser(argc, argv, "{@input | fruits.jpg | input image}");
src = imread("../IMG_7594.png", 0); // Load an image
if (src.empty()) {
std::cout << "Could not open or find the image!\n" << std::endl;
std::cout << "Usage: " << argv[0] << " <Input image>" << std::endl;
return -1;
}
cvtColor(img, lab, COLOR_BGR2LAB);
// dst.create(src.size(), src.type());
// cvtColor(src, src_gray, COLOR_BGR2GRAY);
// namedWindow(window_name, WINDOW_AUTOSIZE);
// createTrackbar("Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold);
// lowThreshold = 100;
CannyThreshold(0, 0);
// waitKey(0);
return 0;
}

View File

@ -0,0 +1,3 @@
#include "cropper.h"

View File

@ -0,0 +1,108 @@
#include "image.h"
#include "ppdefinitions.h"
#ifndef DEBUG
#define DEBUG 0
#endif
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image.h"
#include "stb_image_write.h"
#include <stdio.h>
Image::Image(const char* filename) {
if (read(filename)) {
#if DEBUG == 1
printf("Read %s\n", filename);
#endif
size = w * h * channels;
} else {
#if DEBUG == 1
printf("Failed to read %s\n", filename);
#endif
}
};
Image::Image(int w, int h, int channels) : w(w), h(h), channels(channels) {
size = w * h * channels;
data = new uint8_t[size]();
};
Image::Image(const Image& img) : Image(img.w, img.h, img.channels) {
memcpy(data, img.data, img.size);
};
Image::~Image() {
stbi_image_free(data);
};
int const Image::getWidth() {
return w;
};
int const Image::getChannels() {
return channels;
};
void Image::setPixel(int pixelindex, int value) {
if (value >= 0 && value < 256) {
data[pixelindex] = value;
}
};
bool Image::read(const char* filename) {
data = stbi_load(filename, &w, &h, &channels, 0);
return data != NULL;
};
bool Image::write(const char* filename) {
ImageType type = getFileType(filename);
printf("file type: %d\n", type);
int success = 0;
switch (type) {
case ImageType::PNG:
success = stbi_write_png(filename, w, h, channels, data, w * channels);
break;
case ImageType::JPG:
success = stbi_write_jpg(filename, w, h, channels, data, 100);
break;
case ImageType::BMP:
success = stbi_write_bmp(filename, w, h, channels, data);
break;
case ImageType::TGA:
success = stbi_write_tga(filename, w, h, channels, data);
break;
};
if (success != 0) {
#if DEBUG == 1
printf("\e[32mWrote \e[36m%s\e[0m, %d, %d, %d, %zu\n", filename, w, h, channels, size);
#endif
return true;
} else {
#if DEBUG == 1
printf("\e[31;1m Failed to write \e[36m%s\e[0m, %d, %d, %d, %zu\n", filename, w, h, channels, size);
#endif
return false;
}
};
ImageType Image::getFileType(const char* filename) {
const char* ext = strrchr(filename, '.');
if (ext != nullptr) {
if (strcmp(ext, ".png") == 0) {
return ImageType::PNG;
} else if (strcmp(ext, ".jpg") == 0) {
return ImageType::JPG;
} else if (strcmp(ext, ".bmp") == 0) {
return ImageType::BMP;
} else if (strcmp(ext, ".tga") == 0) {
return ImageType::TGA;
};
};
return ImageType::PNG;
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff