2017-12-21 12:20:57 +01:00
|
|
|
//
|
|
|
|
// Created by Raphael Maenle on 21/12/2017.
|
|
|
|
//
|
|
|
|
#include "../../header/solve.h"
|
2018-01-16 22:53:05 +01:00
|
|
|
#include "../../header/input.h"
|
2017-12-21 12:20:57 +01:00
|
|
|
|
2018-01-19 15:59:19 +01:00
|
|
|
typedef std::vector<std::vector<Point>> Contour_t;
|
|
|
|
typedef std::vector<Vec4i> Hierarchy_t; //hierarchy object is needed for drawContours apparently
|
2018-01-19 15:57:48 +01:00
|
|
|
Mat crop2ContourInv(const Mat & img);
|
2018-01-19 16:00:38 +01:00
|
|
|
Contour_t getLongestContour(Mat bw);
|
2018-01-19 16:12:45 +01:00
|
|
|
int getLongestContourIndex(Contour_t contours);
|
2018-01-19 15:57:48 +01:00
|
|
|
|
2017-12-21 13:07:01 +01:00
|
|
|
void Puzzle::printPuzzle()
|
|
|
|
{
|
2017-12-23 10:11:07 +01:00
|
|
|
cout << "a1: " << endl;
|
|
|
|
a1.printConstraintMatrix();
|
2018-01-16 22:53:05 +01:00
|
|
|
|
2017-12-23 10:11:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Puzzle::printBox()
|
|
|
|
{
|
|
|
|
int i=0;
|
|
|
|
for(auto it:myBox)
|
|
|
|
{
|
|
|
|
cout << "Part " << i++ << ":" << endl;
|
|
|
|
it.print(); cout << endl;
|
|
|
|
|
|
|
|
}
|
2017-12-21 13:07:01 +01:00
|
|
|
}
|
2017-12-21 12:43:31 +01:00
|
|
|
|
2018-01-16 22:53:05 +01:00
|
|
|
|
2017-12-21 13:07:01 +01:00
|
|
|
//puts a puzzlepiece back into its box
|
|
|
|
void Puzzle::putIntoBox()
|
2017-12-21 12:43:31 +01:00
|
|
|
{
|
2017-12-21 13:07:01 +01:00
|
|
|
Part tmpPart;
|
2017-12-23 10:11:07 +01:00
|
|
|
int id = 0;
|
2017-12-21 13:07:01 +01:00
|
|
|
for(int i=0;i<this->getSizeAsCoor().col;i++)
|
2017-12-21 12:43:31 +01:00
|
|
|
{
|
2017-12-21 13:07:01 +01:00
|
|
|
for(int j=0;j<this->getSizeAsCoor().row;j++)
|
|
|
|
{
|
2017-12-23 10:11:07 +01:00
|
|
|
|
2018-01-08 18:33:30 +01:00
|
|
|
tmpPart.m_a1=this->a1.m_constraintMatrix[i+1][j+1];
|
2017-12-23 10:11:07 +01:00
|
|
|
//sets part id
|
|
|
|
tmpPart.SetPartID(id++);
|
|
|
|
// adds all 4 rotations to Box
|
|
|
|
for(int rotations=0;rotations<4;rotations++)
|
|
|
|
{
|
|
|
|
tmpPart.m_a1.shift(1);
|
2018-01-18 22:14:45 +01:00
|
|
|
//TODO! add all other layers with their rotaionvariance here
|
2017-12-23 10:11:07 +01:00
|
|
|
myBox.emplace_back(tmpPart);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-12-21 13:07:01 +01:00
|
|
|
}
|
2017-12-21 12:43:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-21 13:07:01 +01:00
|
|
|
//shuffles the existing box in Puzzle
|
|
|
|
void Puzzle::shuffle()
|
|
|
|
{
|
|
|
|
random_shuffle(myBox.begin(),myBox.end());
|
|
|
|
}
|
2017-12-21 12:43:31 +01:00
|
|
|
|
2017-12-21 13:07:01 +01:00
|
|
|
//deletes all constraints from all abstractionlayers
|
|
|
|
void Puzzle::removeConstrains(coor removeCoordinates)
|
|
|
|
{
|
2017-12-22 22:47:14 +01:00
|
|
|
this->a1.RemoveConstraintOnPosition(removeCoordinates);
|
2017-12-21 13:07:01 +01:00
|
|
|
}
|
2018-01-07 20:08:50 +01:00
|
|
|
void Puzzle::setConstraints(coor setConstraints, Part* constraintPiece)
|
|
|
|
{
|
2018-01-07 21:58:16 +01:00
|
|
|
//dp
|
|
|
|
this->dp.m_constraintMatrix[setConstraints.col][setConstraints.row].DestructionArray.clear();
|
|
|
|
for(auto it:this->tmp_destructionArray)
|
|
|
|
this->dp.m_constraintMatrix[setConstraints.col][setConstraints.row].DestructionArray.emplace_back(it);
|
|
|
|
|
|
|
|
//a1
|
2018-01-07 20:08:50 +01:00
|
|
|
this->a1.SetConstraintOnPosition(setConstraints,constraintPiece->m_a1);
|
|
|
|
}
|
2017-12-21 12:43:31 +01:00
|
|
|
|
|
|
|
void Puzzle::createRandomPuzzle()
|
|
|
|
{
|
2017-12-22 22:47:14 +01:00
|
|
|
a1.CreateRandomPuzzle();
|
2017-12-21 13:07:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Puzzle::createp_box()
|
|
|
|
{
|
2018-01-07 20:08:50 +01:00
|
|
|
for(int i=0;i<cols*rows*4;i++)
|
2018-01-06 23:23:42 +01:00
|
|
|
p_myBox.push_back(&myBox[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//creates a box of puzzlepieces with nothing other than puzzle piece id and correct nr of pieces
|
|
|
|
void Puzzle::createBox(){
|
2018-01-07 20:08:50 +01:00
|
|
|
for(int i=0;i<cols*rows;i++)
|
2018-01-06 23:23:42 +01:00
|
|
|
{
|
|
|
|
Part temp;
|
|
|
|
temp.SetPartID(i);
|
|
|
|
for(uint8_t j=0;j<4;j++)
|
|
|
|
{
|
|
|
|
temp.SetNumOfRotations(j);
|
|
|
|
myBox.push_back(temp);
|
|
|
|
}
|
|
|
|
}
|
2017-12-21 13:07:01 +01:00
|
|
|
}
|
2018-01-07 14:16:57 +01:00
|
|
|
|
|
|
|
bool Puzzle::allSet() {
|
2018-01-07 20:08:50 +01:00
|
|
|
for(auto it:myBox)
|
|
|
|
if(!it.set)
|
|
|
|
return false;
|
|
|
|
return true;
|
2018-01-07 14:16:57 +01:00
|
|
|
}
|
2018-01-07 21:58:16 +01:00
|
|
|
|
|
|
|
void Puzzle::clearMat()
|
|
|
|
{
|
|
|
|
for(unsigned int i=0;i<cols;i++)
|
|
|
|
{
|
|
|
|
for(unsigned int j=0;j<rows;j++)
|
|
|
|
{
|
|
|
|
this->removeConstrains({i,j});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-16 22:53:05 +01:00
|
|
|
|
|
|
|
Mat Puzzle::readImage(int fileIndex, const char* inputDir){
|
|
|
|
|
|
|
|
char indexstr[12];
|
|
|
|
sprintf(indexstr,"%d.jpg",fileIndex);
|
|
|
|
char * inputstr = (char *) malloc(1 + strlen(inputDir)+ strlen(indexstr) );
|
|
|
|
strcpy(inputstr, inputDir);
|
|
|
|
strcat(inputstr,indexstr);
|
|
|
|
//cout<<inputstr<<endl;
|
|
|
|
Mat source = imread(inputstr,1);
|
|
|
|
return source;
|
|
|
|
}
|
2018-01-19 16:12:45 +01:00
|
|
|
Mat Puzzle::resultImage( vector<LogEntry>& log){
|
2018-01-19 15:26:53 +01:00
|
|
|
int Y_size = 1200; // chose this to fit your monitor!
|
2018-01-16 22:53:05 +01:00
|
|
|
int separator = 1;
|
|
|
|
int partHeight = 90;
|
|
|
|
int partWidth;
|
|
|
|
auto imageH = int(round(partHeight* cols));
|
|
|
|
|
|
|
|
if(imageH > Y_size){
|
|
|
|
imageH = Y_size;
|
|
|
|
}
|
|
|
|
partHeight = int(round(imageH / cols));
|
|
|
|
partWidth= partHeight;
|
|
|
|
int imageW = int(round( partWidth*rows));
|
|
|
|
|
2018-01-19 15:26:53 +01:00
|
|
|
int temp = imageW;
|
|
|
|
imageW = imageH;
|
|
|
|
imageH = temp;
|
|
|
|
|
2018-01-16 22:53:05 +01:00
|
|
|
cout<<"imageW "<<imageW <<endl<<"imageH " <<imageH<<endl<<endl;
|
|
|
|
cout<<"partW "<<partWidth <<endl<<"partH " <<partHeight<<endl<<endl;
|
|
|
|
Mat result(imageH,imageW,CV_8UC3);
|
|
|
|
|
2018-01-18 21:36:38 +01:00
|
|
|
char name[100];
|
2018-01-16 22:53:05 +01:00
|
|
|
for (auto it:log)
|
|
|
|
{
|
2018-01-20 20:03:34 +01:00
|
|
|
if (it.myCoor.col == 27 && it.myCoor.row == 5)
|
2018-01-19 15:26:53 +01:00
|
|
|
{
|
|
|
|
;
|
2018-01-19 15:57:48 +01:00
|
|
|
// imshow("result",result);
|
|
|
|
// waitKey(0);
|
2018-01-19 15:26:53 +01:00
|
|
|
}
|
2018-01-16 22:53:05 +01:00
|
|
|
cout << log.size() << endl;
|
|
|
|
cout << log[0].PieceCollector.size() << endl;
|
|
|
|
|
2018-01-19 15:57:48 +01:00
|
|
|
cout << it.PieceCollector[0].second->GetPartID() << endl;
|
2018-01-16 22:53:05 +01:00
|
|
|
|
2018-01-19 15:57:48 +01:00
|
|
|
int imageNumber = it.PieceCollector[0].second->GetPartID();
|
|
|
|
//cout<<"imageIndex: "<< imageNumber << endl;
|
2018-01-16 22:53:05 +01:00
|
|
|
|
2018-01-19 15:57:48 +01:00
|
|
|
sprintf(name, PATH, imageNumber);
|
|
|
|
Mat img = imread(name, 1);
|
2018-01-18 21:36:38 +01:00
|
|
|
|
2018-01-19 15:57:48 +01:00
|
|
|
copyMakeBorder(img,img,200,200,200,200,BORDER_CONSTANT,Scalar(255,255,255));
|
|
|
|
Mat invert = Mat::ones(img.size(), CV_8UC3); // invert for rotation to work correctly
|
|
|
|
bitwise_not ( img, invert );
|
2018-01-20 20:03:34 +01:00
|
|
|
|
|
|
|
if (it.myCoor.col == 35 && it.myCoor.row == 5)
|
2018-01-19 15:57:48 +01:00
|
|
|
{
|
|
|
|
//imshow("img",img);
|
|
|
|
//waitKey(0);
|
|
|
|
;
|
|
|
|
}
|
2018-01-19 15:26:53 +01:00
|
|
|
|
2018-01-16 22:53:05 +01:00
|
|
|
|
2018-01-19 15:57:48 +01:00
|
|
|
int angle = ((int)it.PieceCollector[0].second->GetNumOfRotations())*-90;
|
|
|
|
Point2f center;
|
|
|
|
center.x = img.cols/2;
|
|
|
|
center.y = img.rows/2;
|
|
|
|
Mat RotMatrix = getRotationMatrix2D(center,angle,1);
|
2018-01-19 16:12:45 +01:00
|
|
|
warpAffine(invert,invert,RotMatrix, invert.size());
|
2018-01-19 15:57:48 +01:00
|
|
|
bitwise_not(invert,img);
|
|
|
|
Mat cropped = crop2ContourInv(img);
|
2018-01-18 22:14:45 +01:00
|
|
|
auto ROI_X = int(round(it.myCoor.col*partWidth));
|
|
|
|
auto ROI_Y = int(round(it.myCoor.row*partHeight));
|
2018-01-16 22:53:05 +01:00
|
|
|
// cout<<"ROI X: "<< ROI_X<<endl;
|
|
|
|
// cout<<"ROI Y: "<< ROI_Y<<endl;
|
|
|
|
|
2018-01-18 22:14:45 +01:00
|
|
|
Rect ROI(ROI_X,ROI_Y , partWidth-separator, partHeight-separator); // j is the x coordinate not i!!
|
2018-01-19 15:57:48 +01:00
|
|
|
Mat temp(Scalar(255,255,255));
|
|
|
|
resize(cropped,temp, Size(ROI.width, ROI.height));
|
2018-01-18 22:14:45 +01:00
|
|
|
temp.copyTo(result(ROI));
|
2018-01-16 22:53:05 +01:00
|
|
|
}
|
2018-01-19 15:26:53 +01:00
|
|
|
imshow("result",result);
|
|
|
|
waitKey(0);
|
2018-01-16 22:53:05 +01:00
|
|
|
return result;
|
|
|
|
}
|
2018-01-19 15:57:48 +01:00
|
|
|
|
|
|
|
Mat crop2ContourInv(const Mat & img){ // for white background images
|
|
|
|
Mat grey;
|
|
|
|
cvtColor(img, grey,CV_BGR2GRAY);
|
|
|
|
Contour_t c; Hierarchy_t h;
|
|
|
|
threshold(grey,grey,200,255,THRESH_BINARY_INV);
|
|
|
|
findContours(grey,c,h,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
|
|
|
|
int longest = getLongestContourIndex(c);
|
|
|
|
Rect croppingRect = boundingRect(c[longest]);
|
|
|
|
Mat cropped = img(croppingRect);
|
|
|
|
// imshow("cropped", cropped);
|
|
|
|
return cropped;
|
|
|
|
}
|
2018-01-19 16:00:38 +01:00
|
|
|
|
2018-01-19 16:12:45 +01:00
|
|
|
int getLongestContourIndex(Contour_t contours){
|
2018-01-19 16:00:38 +01:00
|
|
|
double area = 0;
|
|
|
|
double largestArea = 0;
|
|
|
|
size_t largestIndex = 0;
|
|
|
|
for (size_t i = 0; i < contours.size(); ++i)
|
|
|
|
{
|
|
|
|
area = contourArea(contours[i]);
|
|
|
|
if (area < 1e2 || 1e5 < area) continue; //
|
|
|
|
if (area > largestArea) {
|
|
|
|
largestArea = area;
|
|
|
|
largestIndex = i; // i is type size_t, should be converted to int.
|
|
|
|
}
|
|
|
|
}
|
2018-01-19 16:12:45 +01:00
|
|
|
return(largestIndex);
|
|
|
|
}
|