318 lines
8.3 KiB
C++
318 lines
8.3 KiB
C++
|
#include "project.h"
|
||
|
|
||
|
Project::Project(Settings* _settings){
|
||
|
settings=_settings;
|
||
|
filename="";
|
||
|
retrmode=CV_RETR_LIST;
|
||
|
cannythresh=100;
|
||
|
gcode="";
|
||
|
ivcombined=ImageViewer(&combined, "Images");
|
||
|
ivprocessed=ImageViewer(&processed, "Processing");
|
||
|
}
|
||
|
|
||
|
Project::Project(Settings* _settings, std::string _filename){
|
||
|
settings=_settings;
|
||
|
filename=_filename;
|
||
|
retrmode=CV_RETR_LIST;
|
||
|
cannythresh=100;
|
||
|
gcode="";
|
||
|
ivcombined=ImageViewer(&combined, "Images");
|
||
|
ivprocessed=ImageViewer(&processed, "Processing");
|
||
|
}
|
||
|
|
||
|
std::vector<Image>* Project::getImages(){
|
||
|
return &images;
|
||
|
}
|
||
|
|
||
|
int Project::getRetrMode(){
|
||
|
return retrmode;
|
||
|
}
|
||
|
|
||
|
int Project::getCannyThresh(){
|
||
|
return cannythresh;
|
||
|
}
|
||
|
|
||
|
std::map<int, int>* Project::getColoring(){
|
||
|
return &coloring;
|
||
|
}
|
||
|
|
||
|
std::string* Project::getGcode(){
|
||
|
return &gcode;
|
||
|
}
|
||
|
|
||
|
void Project::setFileName(std::string _filename){
|
||
|
filename=_filename;
|
||
|
}
|
||
|
|
||
|
void Project::setRetrMode(int _retrmode){
|
||
|
retrmode=_retrmode;
|
||
|
}
|
||
|
|
||
|
void Project::setCannyThresh(int _cannythresh){
|
||
|
cannythresh=_cannythresh;
|
||
|
}
|
||
|
|
||
|
bool Project::newProj(){
|
||
|
//create files, save def, etc
|
||
|
FILE* f=fopen(filename.c_str(), "w");
|
||
|
if(!f){
|
||
|
fprintf(stderr, "Error> Creating file for project. At: Project::newProj() (file: %s, line: %i)\n", __FILE__, __LINE__);
|
||
|
return false;
|
||
|
}
|
||
|
fprintf(f,"");
|
||
|
fclose(f);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void Project::loadProj(){
|
||
|
//load stuff, deserialize
|
||
|
}
|
||
|
|
||
|
void Project::save(){
|
||
|
//serialize, save to file
|
||
|
}
|
||
|
|
||
|
void Project::close(){
|
||
|
//close project, free up resources;
|
||
|
cv::destroyAllWindows();
|
||
|
}
|
||
|
|
||
|
bool Project::combine(){
|
||
|
//get col and row count
|
||
|
int colmax=0, rowmax=0;
|
||
|
for(std::vector<Image>::iterator it=images.begin(); it<images.end(); it++){
|
||
|
//get current mat
|
||
|
cv::Mat cur=*it->getMat();
|
||
|
|
||
|
//get resized mat
|
||
|
cv::Mat resz;
|
||
|
cv::resize(cur, resz, cv::Size(cur.cols*it->getScale(), cur.rows*it->getScale()));
|
||
|
|
||
|
//get cropped mat
|
||
|
cv::Mat crop=resz(cv::Rect(it->getCrop1().getX(), it->getCrop1().getY(), (it->getCrop2().getX()-it->getCrop1().getX())*it->getScale(), (it->getCrop2().getY()-it->getCrop1().getY())*it->getScale()));
|
||
|
|
||
|
//crop debug
|
||
|
if(settings->isDebug()){
|
||
|
ImageViewer* iv=new ImageViewer(crop, "DEBUG:combine> "+it->getFilename());
|
||
|
iv->show();
|
||
|
}
|
||
|
|
||
|
if(it->getPosition().getX()+crop.cols > colmax){
|
||
|
colmax=it->getPosition().getX()+crop.cols;
|
||
|
}
|
||
|
if(it->getPosition().getY()+crop.rows > rowmax){
|
||
|
rowmax=it->getPosition().getY()+crop.rows;
|
||
|
}
|
||
|
|
||
|
//cleanup
|
||
|
resz.release();
|
||
|
crop.release();
|
||
|
}
|
||
|
|
||
|
if(settings->isDebug()){
|
||
|
printf("DEBUG:combine> colmax=%i, rowmax=%i\n", colmax, rowmax);
|
||
|
}
|
||
|
|
||
|
//create new mat
|
||
|
combined=cv::Mat::zeros(rowmax, colmax, CV_8UC3);
|
||
|
|
||
|
//add layers
|
||
|
for(std::vector<Image>::iterator it=images.begin(); it<images.end(); it++){
|
||
|
//get current mat
|
||
|
cv::Mat cur=*it->getMat();
|
||
|
|
||
|
//get resized mat
|
||
|
cv::Mat resz;
|
||
|
cv::resize(cur, resz, cv::Size(cur.cols*it->getScale(), cur.rows*it->getScale()));
|
||
|
|
||
|
//get cropped mat
|
||
|
cv::Mat crop=resz(cv::Rect(it->getCrop1().getX()*it->getScale(), it->getCrop1().getY()*it->getScale(), (it->getCrop2().getX()-it->getCrop1().getX())*it->getScale(), (it->getCrop2().getY()-it->getCrop1().getY())*it->getScale()));
|
||
|
|
||
|
//add layer
|
||
|
crop.copyTo(combined(cv::Rect(it->getPosition().getX(), it->getPosition().getY(), crop.cols, crop.rows)));
|
||
|
|
||
|
//cleanup
|
||
|
resz.release();
|
||
|
crop.release();
|
||
|
}
|
||
|
|
||
|
//show results
|
||
|
ivcombined.refresh();
|
||
|
|
||
|
//everything alright
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Project::process(){
|
||
|
if(combined.empty()){
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//convert mat to gray
|
||
|
cv::Mat graymat;
|
||
|
cv::cvtColor(combined, graymat, CV_BGR2GRAY);
|
||
|
if(settings->isDebug()){
|
||
|
ImageViewer* iv=new ImageViewer(graymat, "DEBUG:process> cvtColor");
|
||
|
iv->show();
|
||
|
}
|
||
|
|
||
|
//blur edges
|
||
|
cv::blur(graymat, graymat, cv::Size(3, 3));
|
||
|
if(settings->isDebug()){
|
||
|
ImageViewer* iv=new ImageViewer(graymat, "DEBUG:process> blur");
|
||
|
iv->show();
|
||
|
}
|
||
|
|
||
|
//canny edge detection
|
||
|
cv::Mat canny;
|
||
|
cv::Canny(graymat, canny, cannythresh, cannythresh*2, 3);
|
||
|
if(settings->isDebug()){
|
||
|
ImageViewer* iv=new ImageViewer(canny, "DEBUG:process> Canny");
|
||
|
iv->show();
|
||
|
}
|
||
|
|
||
|
//find contours
|
||
|
cv::findContours(canny, contours, hierarchy, retrmode, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
|
||
|
|
||
|
//build color map if not ready
|
||
|
if(coloring.size()!=contours.size()){
|
||
|
coloring.clear();
|
||
|
for(int i=0; i<contours.size(); i++){
|
||
|
coloring[i]=-1; //set to default head to use
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//draw output
|
||
|
processed=cv::Mat::zeros(canny.size(), CV_8UC3);
|
||
|
for(int i=0; i<contours.size(); i++){
|
||
|
cv::Scalar color=cv::Scalar(30, 200, 30);
|
||
|
cv::drawContours(processed, contours, i, color, 2, 8, hierarchy, 0, cv::Point());
|
||
|
}
|
||
|
|
||
|
//show results
|
||
|
ivprocessed.refresh();
|
||
|
|
||
|
//cleanup
|
||
|
graymat.release();
|
||
|
canny.release();
|
||
|
|
||
|
//it's k
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Project::printEdge(int n){
|
||
|
//the same story
|
||
|
if(combined.empty()){
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//draw contours
|
||
|
processed=cv::Mat::zeros(processed.size(), CV_8UC3);
|
||
|
for(int i=0; i<contours.size(); i++){
|
||
|
cv::Scalar color=cv::Scalar(30, 200, 30);
|
||
|
cv::drawContours(processed, contours, i, color, 2, 8, hierarchy, 0, cv::Point());
|
||
|
}
|
||
|
|
||
|
//highlight "The One"
|
||
|
cv::Scalar color=cv::Scalar(30, 30, 200);
|
||
|
cv::drawContours(processed, contours, n, color, 2, 8, hierarchy, 0, cv::Point());
|
||
|
|
||
|
//show results
|
||
|
ivprocessed.refresh();
|
||
|
|
||
|
//kkk
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Project::generateGcode(){
|
||
|
//check if the stuff is set
|
||
|
if(contours.empty()){
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//clear previous gcode
|
||
|
gcode="";
|
||
|
|
||
|
//statistics
|
||
|
unsigned int lines=0;
|
||
|
double maxX=0, maxY=0;
|
||
|
|
||
|
//add info
|
||
|
gcode+=";Generated by: PlottWareControl\n;Project: "+filename+"\n;Program created by: Fandly Gergo (fandlygergo@gmail.hu, systemtest.tk)\n\n\n\n";
|
||
|
|
||
|
//startup code
|
||
|
gcode+="G90 ;absolute positioning\n";
|
||
|
gcode+="M17 ;enable steppers\n";
|
||
|
gcode+="T1000 ;deselect all tools\n";
|
||
|
gcode+="G28 ;home axises\n";
|
||
|
lines+=10;
|
||
|
|
||
|
//iterate through contours
|
||
|
for(int i=0; i<contours.size(); i++){
|
||
|
//if we need to eliminate the contour...
|
||
|
if(coloring[i]==0){
|
||
|
continue; //we do so
|
||
|
}
|
||
|
|
||
|
if(coloring[i]==-1){
|
||
|
coloring[i]=1; //set to the default if not set...
|
||
|
}
|
||
|
|
||
|
//start contour drawing
|
||
|
gcode+=";printing contour #"+std::to_string(i)+"\n";
|
||
|
//select tool
|
||
|
gcode+="T"+std::to_string(coloring[i])+"\n";
|
||
|
|
||
|
//move to first point
|
||
|
gcode+="G0 X"+std::to_string(contours[i][0].x/10.0)+" Y"+std::to_string(contours[i][0].y/10.0)+"\n";
|
||
|
if(contours[i][0].x/10.0 > maxX){
|
||
|
maxX=contours[i][0].x/10.0;
|
||
|
}
|
||
|
if(contours[i][0].y/10.0 > maxY){
|
||
|
maxY=contours[i][0].y/10.0;
|
||
|
}
|
||
|
|
||
|
//move pen down
|
||
|
gcode+="M300 S10\n";
|
||
|
lines+=4;
|
||
|
|
||
|
//iterate through points
|
||
|
for(int o=1; o<contours[i].size(); o++){
|
||
|
gcode+="G1 X"+std::to_string(contours[i][o].x/10.0)+" Y"+std::to_string(contours[i][o].y/10.0)+"\n";
|
||
|
if(contours[i][o].x/10.0 > maxX){
|
||
|
maxX=contours[i][o].x/10.0;
|
||
|
}
|
||
|
if(contours[i][o].y/10.0 > maxY){
|
||
|
maxY=contours[i][o].y/10.0;
|
||
|
}
|
||
|
lines++;
|
||
|
}
|
||
|
|
||
|
//lift up pen
|
||
|
gcode+="M300 S50\n";
|
||
|
lines+=1;
|
||
|
}
|
||
|
|
||
|
//end
|
||
|
gcode+="T1000 ;deselect tool\n";
|
||
|
gcode+="M18 ;disable steppers\n";
|
||
|
gcode+="M2 ;program end\n";
|
||
|
lines+=3;
|
||
|
|
||
|
//print "final thoughts"
|
||
|
lines+=7;
|
||
|
gcode+="\n\n\n;Line count: "+std::to_string(lines)+"\n;Max X: "+std::to_string(maxX)+"\n;Max Y: "+std::to_string(maxY)+"\n;ENJOY!";
|
||
|
}
|
||
|
|
||
|
bool Project::exportGcode(std::string file){
|
||
|
FILE* f=fopen(file.c_str(), "w");
|
||
|
if(!f){
|
||
|
fprintf(stderr, "Error> Can't create file for gcode export. At: Project::exportGcode(std::string file) (file: %s, line: %i)\n", __FILE__, __LINE__);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
fprintf(f, "%s", gcode.c_str());
|
||
|
fclose(f);
|
||
|
return true;
|
||
|
}
|