Skip to content
This repository has been archived by the owner on Sep 17, 2021. It is now read-only.

Commit

Permalink
Refactor!
Browse files Browse the repository at this point in the history
* fix global pool. fix mess in global.xml
* thread-safe in global pool.
* refactor a lot (for thread safe. some static varibles are removed)
* bug fix in recTime.
  • Loading branch information
JamzumSum committed Aug 10, 2019
1 parent b30dbcc commit d5e05f0
Show file tree
Hide file tree
Showing 25 changed files with 6,091 additions and 634 deletions.
42 changes: 24 additions & 18 deletions Cuckoo/Cuckoo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "Cuckoo.h"
#include "Dodo.h"
#include "eagle.h"
#include "converter.h"

using namespace std;
using namespace cv;
Expand All @@ -10,7 +11,7 @@ using namespace cv;
#define Showline if constexpr(0)
#define draw(func, img, from, to, color) Show##func func(img, from, to, color)

static knnReader reader;
extern thread_local const Converter* root;

static int count(Mat img, Rect range, int delta) {
assert(img.isContinuous());
Expand Down Expand Up @@ -88,7 +89,7 @@ void Measure::recStaffLines() {

for (Rect& i : region) {
if (i.height < 5 * i.width
&& (getkey(characterWidth) ? (i.width > getkey(characterWidth) / 2) : 1)
&& (global["characterWidth"].isInit() ? (i.width > global["characterWidth"] / 2) : 1)
) {
if (i.height > rows[1][1] - rows[0][1]
|| i.height < i.width
Expand Down Expand Up @@ -194,7 +195,7 @@ void Measure::recTime() {
vector<vector<Point>> cont;
auto predictLenth = [&inv, &picValue, &cont, this]() -> int {
int predLen = 0;
if (org.rows < getkey(rowLenth) * 2 && org.rows > getkey(rowLenth) / 2) {
if (org.rows < global["rowLenth"] * 2 && org.rows > global["rowLenth"] / 2) {
inv = 255 - Morphology(picValue, picValue.rows / 3, false, true);
findContours(inv, cont, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

Expand All @@ -215,10 +216,10 @@ void Measure::recTime() {
Rect temp = boundingRect(i);
predLen = max((int)predLen, temp.height);
}
getkey(valueSignalLen) += predLen;
const_cast<GlobalUnit&>(global["valueSignalLen"]) += predLen;
}
else {
predLen = getkey(valueSignalLen);
predLen = global["valueSignalLen"];
}
return predLen;
};
Expand Down Expand Up @@ -251,15 +252,16 @@ void Measure::recTime() {

vector<Rect> region = time_denoise(); //去掉节拍记号再往下的乱七八糟的东西

for (Rect &i: region) {
for (const Rect &i: region) {
int sum1 = 0, sum2 = 0, sum3 = 0;
sum1 = count(picValue, i, -2);
sum2 = count(picValue, i, 2);
sum3 = count(picValue, i, 1);
if (i.height <= predLen / 2 && !sum1 && !sum2) {
sum1--; sum2--;
sum1--; sum2--; //TODO: 我写的这是啥?
//PS. 这好像是检查二分音符
}
Value newc = time.beat_type / (int)pow(2, max(sum1, !sum3 && sum2 ? sum2 - 1 : sum2));
Value newc = time.beat_type / (float)pow(2, max(sum1, !sum3 && sum2 ? sum2 - 1 : sum2));
newc.dot = !sum3 && sum2;
timeValue[i.x + i.width / 2] = newc;
}
Expand Down Expand Up @@ -335,10 +337,10 @@ EasyNote Measure::dealWithIt(const Rect& region) {
cont.clear(); cont.shrink_to_fit();
for (Rect& i : re) {
if (i.height < 2.5 * i.width
&& (getkey(characterWidth) ? (i.width > getkey(characterWidth) / 2) : 1)
&& (global["characterWidth"].isInit() ? (i.width > global["characterWidth"] / 2) : 1)
&& i.height > i.width) {
EasyNote newNote;
newNote.acceptRecData(reader.rec(img(i), 45.0f));
newNote.acceptRecData(reader->rec(img(i), 45.0f));
newNote.string = whichLine(Rect(region.tl() + i.tl(), i.size()), rows);
if (newNote.fret > 0 && newNote.string) {
newNote.pos = region.x + i.x + i.width / 2;
Expand Down Expand Up @@ -368,10 +370,10 @@ EasyNote Measure::dealWithIt(const Rect& region) {
cont.clear();
for (Rect& i : re) {
if (i.height < 2.5 * i.width
&& (getkey(characterWidth) ? (i.width > getkey(characterWidth) / 2) : 1)
&& (global["characterWidth"].isInit() ? (i.width > global["characterWidth"] / 2) : 1)
&& i.height > i.width) {
EasyNote newNote;
newNote.acceptRecData(reader.rec(img(i), 45.0f));
newNote.acceptRecData(reader->rec(img(i), 45.0f));
newNote.string = whichLine(Rect(region.tl() + i.tl(), i.size()), rows);
if (newNote.fret > 0 && newNote.string) {
newNote.pos = region.x + i.x + i.width / 2;
Expand All @@ -389,7 +391,7 @@ EasyNote Measure::dealWithIt(const Rect& region) {
EasyNote newNote;
newNote.string = whichLine(region, rows);
newNote.pos = i + trueWidth / 2;
newNote.acceptRecData(reader.rec(test, 25.0f));
newNote.acceptRecData(reader->rec(test, 25.0f));
if (newNote.fret > 0 && newNote.string) return newNote;
}
return EasyNote::invalid();
Expand All @@ -399,7 +401,7 @@ EasyNote Measure::dealWithIt(const Rect& region) {
for (int i = 0; i < img.rows - trueHeight; i++) {
Mat test = img(Range(i, i + trueHeight), Range::all());
EasyNote newNote;
newNote.acceptRecData(reader.rec(test, 25.0f));
newNote.acceptRecData(reader->rec(test, 25.0f));
if (newNote.fret > 0) {
newNote.string = whichLine(Range(i, i + trueHeight), rows);
if (newNote.string) {
Expand All @@ -422,9 +424,9 @@ EasyNote Measure::dealWithIt(const Rect& region) {
}

Measure::Measure(Mat origin, size_t id)
: id(id), ImageProcess(origin)
: id(id), ImageProcess(origin), reader(root->Reader.operator CharReader*())
{
maxCharacterWidth = getkey(characterWidth) / 2;
maxCharacterWidth = global["characterWidth"] / 2;
maxCharacterHeight = maxCharacterWidth + 1;
}

Expand Down Expand Up @@ -511,15 +513,15 @@ EasyNote Measure::recNum(const cv::Rect& rect) {
newNote.string = whichLine(rect, rows); //几何关系判断string
if (!newNote.string) return EasyNote::invalid();
try {
newNote.acceptRecData(reader.rec(number)); //识别数字fret
newNote.acceptRecData(reader->rec(number)); //识别数字fret
if (newNote.fret < 0) return EasyNote::invalid(); //较大的几率不是数字
}
catch (runtime_error ex) {
throw ex;
}

newNote.pos = rect.width / 2 + rect.x;
getkey(characterWidth) += rect.width;
const_cast<GlobalUnit&>(global["characterWidth"]) += rect.width;

maxCharacterWidth = max(maxCharacterWidth, rect.width);
maxCharacterHeight = max(maxCharacterHeight, rect.height);
Expand Down Expand Up @@ -576,3 +578,7 @@ void Measure::dealWithLink(const pair<Vec4i, double>& arcVec) {
const_cast<EasyNote*>(rnote)->addNotation('l');
}
}

inline ImageProcess::ImageProcess(cv::Mat origin) : org(origin), global(root->Global) {
assert(org.empty() != true);
}
14 changes: 8 additions & 6 deletions Cuckoo/Cuckoo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
#include "cv.h"
#include "music.h"
#include "global.h"
#include "eagle.h"
#include <atomic>

#if _DEBUG
#ifdef _DEBUG
#define imdebug(title, img) imshow((title), img); cv::waitKey()
#define myassert(msg) _wassert((msg), __FILEW__, __LINE__)
#else
#define imdebug(title, img)
#define myassert(msg)
#endif

extern GlobalPool global;

class EasyNote {
private:
Expand Down Expand Up @@ -39,7 +41,7 @@ class EasyNote {
fret = 0;
switch (c) {
case 'x': addNotation('x'); break;
default: _wassert(L"invalid rec val: " + c, __FILEW__, __LINE__);
default: myassert(L"invalid rec val: " + c);
}
}
}
Expand Down Expand Up @@ -96,10 +98,9 @@ class ChordSet: public std::vector<EasyNote>
class ImageProcess {
protected:
cv::Mat org;
const GlobalPool& global;
public:
ImageProcess(cv::Mat origin) : org(origin) {
assert(org.empty() != true);
}
ImageProcess(cv::Mat origin);
};

class Measure: ImageProcess {
Expand All @@ -110,6 +111,7 @@ class Measure: ImageProcess {
std::map<unsigned, ChordSet> notes;
cv::Mat denoised;
std::vector<cv::Vec4i> rows;
const CharReader* reader;

void recStaffLines();
void recTime();
Expand Down
2 changes: 2 additions & 0 deletions Cuckoo/cpp.hint
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
// 如函数和宏的名称。
// 有关详细信息,请参见 https://go.microsoft.com/fwlink/?linkid=865984
#define CV_NOEXCEPT
#define assert(expression) ((void)0)
#define assert(expression) (void)( (!!(expression)) || (_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) )
37 changes: 24 additions & 13 deletions Cuckoo/eagle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using namespace std;
using namespace cv;

bool savepic = 0;
thread_local extern const Converter* root;

/**
识别传入的字符.
Expand All @@ -22,7 +22,7 @@ bool savepic = 0;
@retval map of(-1->-1) is returned if 'reshape' throws an error; or no result has a possibility
greater than threshold.
*/
map<char, float> knnReader::rec(Mat character, float threshold) {
map<char, float> knnReader::rec(Mat character, float threshold) const {
cvtColor(character, character, CV_GRAY2BGR);
character = perspect(character, getPreferWidth(), getPreferHeight());

Expand All @@ -31,7 +31,7 @@ map<char, float> knnReader::rec(Mat character, float threshold) {
(character.isContinuous() ? character : character.clone()).
reshape(1, 1).convertTo(tmp, CV_32FC1, 1.0 / 255.0);

load(defaultCSV); //lazy load
load(prop.defaultCSV); //lazy load
assert(knn->isTrained()); //post condition
knn->findNearest(tmp, 5, res, neighbour, dist);

Expand All @@ -41,26 +41,26 @@ map<char, float> knnReader::rec(Mat character, float threshold) {
if (a < threshold) {
ret.insert(make_pair(static_cast<char>(neighbour.at<float>(0, j)), a));
}
else if (savepic && j == 0) {
savePic(picFolder, character);
else if (prop.savePic && j == 0) {
savePic(prop.picFolder, character);
break;
}
}
return ret.empty() ? map<char, float>({ {-1, -1.0f} }) : ret;
}

void CharReader::train(string save) {
void CharReader::train(Property prop) {
//trainData 个数*大小
//Labels 个数*10
Mat trainData, Label ,CSV;
//录入训练样本和标记
vector<string> fileList;
string path = samplePath;
string path = prop.samplePath;

for (char i: readable) {
ls((path + i).c_str(), fileList);
for (int j = 0; j < (int)fileList.size(); j++) {
Mat tmp = imread(string(fileList[j]));
Mat tmp = imread(fileList[j]);
trainData.push_back(tmp.reshape(1, 1));
Label.push_back(i); //与trainData对应的标记
}
Expand All @@ -69,20 +69,24 @@ void CharReader::train(string save) {
Label.convertTo(Label,CV_32F);
trainData.convertTo(trainData, CV_32FC1, 1.0 / 255.0);
hconcat(Label, trainData, CSV);
//Ptr<TrainData> tData = TrainData::create(trainData, ROW_SAMPLE, Label);
ofstream file(save);
ofstream file(prop.defaultCSV);
file << format(CSV, Formatter::FMT_CSV);
file.close();
//remove existed cache.
if (isExist("knn.xml")) remove("knn.xml");
}

CharReader::CharReader() :prop(root->Prop) {}
CharReader::CharReader(string csv) : prop(root->Prop) { load(csv); }

/*
load train data from a csv file.
@name CharReader::load
@param csv string, path of the csv file.
effects: this->knn->isTrain() == true
*/
void knnReader::load(string csv) {
void knnReader::load(string csv) const {
if (knn->isTrained()) return; //return if trained.

if(!isExist(csv)) FreeResFile(IDR_ML_CSV1, "ML_CSV", csv);
Expand All @@ -97,17 +101,24 @@ void knnReader::load(string csv) {
Mat Label;
trainData->getResponses().convertTo(Label,CV_32S);
knn->train(trainData->getSamples(),ROW_SAMPLE,Label);
knn->save("knn.xml");
}

knnReader::knnReader(): CharReader(){
if (isExist("knn.xml")) knn = KNearest::load<KNearest>("knn.xml");
else knn = KNearest::create();
}

/*
the strategy when train data is lost or destroyed.
@param csv string, the csv file path.
@retval true if the strategy suggests exit.
*/
bool CharReader::onDestroyed(const string& csv) noexcept {
bool CharReader::onDestroyed(const string& csv) const noexcept {
FreeResFile(IDR_ML_CSV1, "ML_CSV", csv);
Ptr<TrainData> trainData = TrainData::loadFromCSV(csv, 0, 0, -1);
return false;
}

CharReader::~CharReader() {} //virtual dtor.
CharReader::~CharReader() {} //virtual dtor.
void CharReader::load(string) const {}
27 changes: 15 additions & 12 deletions Cuckoo/eagle.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#pragma once
#include "stdafx.h"
#include "global.h"
#include "opencv.hpp"
#include "ml.hpp"
#include "converter.h"

using cv::Mat;
using std::string;
Expand All @@ -16,21 +17,22 @@ class CharReader {
int preferHeight = 14;

protected:
virtual bool onDestroyed(const string& csv) noexcept;
const Property& prop;
virtual bool onDestroyed(const string& csv) const noexcept;

public:

static void train(string save);
static void train(Property save);

virtual map<char, float> rec(Mat character, float threshold = 60.0f) = 0;
virtual map<char, float> rec(Mat character, float threshold = 60.0f) const = 0;
virtual bool isTrained() = 0;
virtual void load(string csv) = 0;
virtual void load(string csv) const = 0;

CharReader() {}
CharReader(string csv) { load(csv); }
CharReader();
CharReader(string csv);

int getPreferWidth() { return preferWidth; }
int getPreferHeight() { return preferHeight; }
int getPreferWidth() const { return preferWidth; }
int getPreferHeight() const { return preferHeight; }
void setPreferSize(int width, int height) {
preferWidth = width;
preferHeight = height;
Expand All @@ -41,11 +43,12 @@ class CharReader {

class knnReader: public CharReader {
private:
cv::Ptr<KNearest> knn = KNearest::create();
cv::Ptr<KNearest> knn;
using CharReader::onDestroyed;
public:
bool isTrained() { return knn->isTrained(); }

map<char, float> rec(Mat character, float threshold = 60.0f);
void load(string csv);
map<char, float> rec(Mat character, float threshold = 60.0f) const;
void load(string csv) const;
knnReader();
};
6 changes: 3 additions & 3 deletions Cuckoo/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void LineFinder::findRow(vector<Vec4i> & lines) {
vector<Vec4i> copy(lines);
thickness.resize(rcls.size());
lines.resize(rcls.size());
std::transform(rcls.begin(), rcls.end(), thickness.begin(), [](const vector<Vec4i> x) -> int { int i = (int)x.size(); getkey(lineThickness) += i; return int(i); });
std::transform(rcls.begin(), rcls.end(), thickness.begin(), [this](const vector<Vec4i> x) -> int { int i = (int)x.size(); const_cast<GlobalUnit&>(global["lineThickness"]) += i; return int(i); });
std::transform(rcls.begin(), rcls.end(), lines.begin(), [](const vector<Vec4i> x) -> Vec4i {return x[x.size() / 2]; });

upper = std::min(lines[5][1], lines[5][3]);
Expand Down Expand Up @@ -208,8 +208,8 @@ void LineFinder::findCol(vector<Vec4i> & lines) {


for (size_t i = 1; i < lines.size(); i++) {
if (lines[i][0] - lines[i - 1][0] >= max(16, getkey(colLenth) / 5)) {
getkey(colLenth) += lines[i][0] - lines[i - 1][0];
if (lines[i][0] - lines[i - 1][0] >= max(16, global["colLenth"] / 5)) {
const_cast<GlobalUnit&>(global["colLenth"]) += lines[i][0] - lines[i - 1][0];
}
}

Expand Down
Loading

0 comments on commit d5e05f0

Please sign in to comment.