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:
parent
e7b447208c
commit
bf2fa97abe
24
code/autocropper/CMakeLists.txt
Normal file
24
code/autocropper/CMakeLists.txt
Normal 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 |
14
code/autocropper/include/cropper.h
Normal file
14
code/autocropper/include/cropper.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef CROPPER_H
|
||||
#define CROPPER_H
|
||||
|
||||
#include "image.h"
|
||||
|
||||
|
||||
class Cropper {
|
||||
private:
|
||||
Image picture;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //CROPPER_H
|
||||
38
code/autocropper/include/image.h
Normal file
38
code/autocropper/include/image.h
Normal 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
|
||||
1
code/autocropper/include/ppdefinitions.h
Normal file
1
code/autocropper/include/ppdefinitions.h
Normal file
@ -0,0 +1 @@
|
||||
#define DEBUG 1
|
||||
98
code/autocropper/main.cpp
Normal file
98
code/autocropper/main.cpp
Normal 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;
|
||||
}
|
||||
3
code/autocropper/src/cropper.cpp
Normal file
3
code/autocropper/src/cropper.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "cropper.h"
|
||||
|
||||
|
||||
108
code/autocropper/src/image.cpp
Normal file
108
code/autocropper/src/image.cpp
Normal 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;
|
||||
};
|
||||
|
||||
7987
code/externallibraries/stbimagehelpers/stb_image.h
Normal file
7987
code/externallibraries/stbimagehelpers/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
2634
code/externallibraries/stbimagehelpers/stb_image_resize.h
Normal file
2634
code/externallibraries/stbimagehelpers/stb_image_resize.h
Normal file
File diff suppressed because it is too large
Load Diff
1724
code/externallibraries/stbimagehelpers/stb_image_write.h
Normal file
1724
code/externallibraries/stbimagehelpers/stb_image_write.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user