|
@@ -280,6 +280,7 @@ CSolaCutPointReid::CSolaCutPointReid(ConfigParam&cp, int stemType, CGcvLogger*pL
|
|
m_pImginfoBin(0),
|
|
m_pImginfoBin(0),
|
|
m_pImgCutPoint(0)
|
|
m_pImgCutPoint(0)
|
|
{
|
|
{
|
|
|
|
+ //m_stem_type -- 0-接穗, 1-砧木
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -302,10 +303,10 @@ int CSolaCutPointReid::cut_point_reid(
|
|
)
|
|
)
|
|
{
|
|
{
|
|
if (m_stem_type == 0) {
|
|
if (m_stem_type == 0) {
|
|
- m_imgId = getImgId(img_type::sola_rs_reid);
|
|
|
|
|
|
+ m_imgId = getImgId(img_type::sola_sc_reid);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- m_imgId = getImgId(img_type::sola_sc_reid);
|
|
|
|
|
|
+ m_imgId = getImgId(img_type::sola_rs_reid);
|
|
}
|
|
}
|
|
|
|
|
|
//1 image segment
|
|
//1 image segment
|
|
@@ -382,7 +383,7 @@ int CSolaCutPointReid::cut_point_reid(
|
|
t = clock();
|
|
t = clock();
|
|
if (1000.0*((float)(t - t0)) / CLOCKS_PER_SEC>(float)m_cparam.timeout_proc) {
|
|
if (1000.0*((float)(t - t0)) / CLOCKS_PER_SEC>(float)m_cparam.timeout_proc) {
|
|
if (m_pLogger) {
|
|
if (m_pLogger) {
|
|
- m_pLogger->ERRORINFO(m_imgId + " rootstock reid timeout.");
|
|
|
|
|
|
+ m_pLogger->ERRORINFO(m_imgId + " sola cut points reid timeout.");
|
|
}
|
|
}
|
|
throw_msg(m_imgId + " time out");
|
|
throw_msg(m_imgId + " time out");
|
|
}
|
|
}
|
|
@@ -413,27 +414,48 @@ int CSolaCutPointReid::cut_point_reid(
|
|
throw_msg(m_imgId + " no valid object");
|
|
throw_msg(m_imgId + " no valid object");
|
|
}
|
|
}
|
|
|
|
|
|
- vector<cv::Point> cut_curve;
|
|
|
|
- cv::RotatedRect retval;
|
|
|
|
- find_cut_curve(contours[max_idx], cut_curve, retval);
|
|
|
|
|
|
+ // 找到切口处y值
|
|
|
|
+ int minx, maxx, miny, maxy;
|
|
|
|
+ int cut_miny, cut_midy, cut_maxy;
|
|
|
|
+
|
|
|
|
+ find_cut_ys(contours[max_idx],
|
|
|
|
+ minx, maxx, miny, maxy,
|
|
|
|
+ cut_miny, cut_midy, cut_maxy);
|
|
|
|
+
|
|
|
|
+ // 夹爪基面的y
|
|
|
|
+ int base_y = maxy; // 砧木情况
|
|
|
|
+ if (m_stem_type == 0) {// 接穗情况
|
|
|
|
+ base_y = miny;
|
|
|
|
+ }
|
|
if (m_cparam.image_show) {
|
|
if (m_cparam.image_show) {
|
|
cv::Mat tmp = m_grayImg.clone();
|
|
cv::Mat tmp = m_grayImg.clone();
|
|
- cv::ellipse(tmp, retval, cv::Scalar(200));
|
|
|
|
- imshow_wait("gray_ellipse", tmp);
|
|
|
|
|
|
+ cv::line(tmp, cv::Point(minx, cut_miny), cv::Point(maxx, cut_miny), cv::Scalar(200));
|
|
|
|
+ cv::line(tmp, cv::Point(minx, cut_midy), cv::Point(maxx, cut_midy), cv::Scalar(200));
|
|
|
|
+ cv::line(tmp, cv::Point(minx, cut_maxy), cv::Point(maxx, cut_maxy), cv::Scalar(200));
|
|
|
|
+ cv::line(tmp, cv::Point(minx, base_y), cv::Point(maxx, base_y), cv::Scalar(255));
|
|
|
|
+ imshow_wait("gray_lines", tmp);
|
|
|
|
+ }
|
|
|
|
+ if (m_stem_type == 0) {//接穗,坐标左上角位0点
|
|
|
|
+ posinfo.sc_reid_sola_upoint_x = base_y; //夹爪基面的y, 砧木在下方(夹爪的上沿),接穗在上方(夹爪的下沿)
|
|
|
|
+ posinfo.sc_reid_sola_upoint_y = fabs(cut_miny - base_y) + 1 ;
|
|
|
|
+ posinfo.sc_reid_sola_cpoint_x = minx;
|
|
|
|
+ posinfo.sc_reid_sola_cpoint_y = fabs(cut_midy - base_y) + 1;
|
|
|
|
+ posinfo.sc_reid_sola_lpoint_x = minx;
|
|
|
|
+ posinfo.sc_reid_sola_lpoint_y = fabs(cut_maxy - base_y) + 1;
|
|
|
|
+ }
|
|
|
|
+ else {//砧木,坐标左下角位0点
|
|
|
|
+ posinfo.rs_reid_sola_upoint_x = m_grayImg.rows - base_y - 1; //夹爪基面的y, 砧木在下方(夹爪的上沿),接穗在上方(夹爪的下沿)
|
|
|
|
+ posinfo.rs_reid_sola_upoint_y = fabs(cut_miny - base_y) + 1;
|
|
|
|
+ posinfo.rs_reid_sola_cpoint_x = minx;
|
|
|
|
+ posinfo.rs_reid_sola_cpoint_y = fabs(cut_midy - base_y) + 1;
|
|
|
|
+ posinfo.rs_reid_sola_lpoint_x = minx;
|
|
|
|
+ posinfo.rs_reid_sola_lpoint_y = fabs(cut_maxy - base_y) + 1;
|
|
}
|
|
}
|
|
-
|
|
|
|
- posinfo.rs_reid_sola_upoint_x = retval.center.x;
|
|
|
|
- posinfo.rs_reid_sola_upoint_y = retval.center.y - retval.size.height / 2;
|
|
|
|
- posinfo.rs_reid_sola_cpoint_x = retval.center.x;
|
|
|
|
- posinfo.rs_reid_sola_cpoint_y = retval.center.y;
|
|
|
|
- posinfo.rs_reid_sola_lpoint_x = retval.center.x;
|
|
|
|
- posinfo.rs_reid_sola_lpoint_y = retval.center.y + retval.size.height/2;
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
if(m_pLogger){
|
|
if(m_pLogger){
|
|
stringstream buff;
|
|
stringstream buff;
|
|
- buff<<m_imgId<<" rootstock image, rs_cut_upoint("<< posinfo.rs_reid_sola_upoint_x
|
|
|
|
|
|
+ buff<<m_imgId<<" sola rootstock(scion) image, rs_cut_upoint("<< posinfo.rs_reid_sola_upoint_x
|
|
<<","<< posinfo.rs_reid_sola_upoint_y <<")"
|
|
<<","<< posinfo.rs_reid_sola_upoint_y <<")"
|
|
<<", rs_cut_cpoint=("<< posinfo.rs_reid_sola_cpoint_x
|
|
<<", rs_cut_cpoint=("<< posinfo.rs_reid_sola_cpoint_x
|
|
<< "," << posinfo.rs_reid_sola_cpoint_y << ")"
|
|
<< "," << posinfo.rs_reid_sola_cpoint_y << ")"
|
|
@@ -453,7 +475,9 @@ int CSolaCutPointReid::cut_point_reid(
|
|
|
|
|
|
//2 cut point int gray image
|
|
//2 cut point int gray image
|
|
cv::Mat tmp = m_grayImg.clone();
|
|
cv::Mat tmp = m_grayImg.clone();
|
|
- cv::ellipse(tmp, retval, cv::Scalar(200));
|
|
|
|
|
|
+ cv::line(tmp, cv::Point(minx, cut_miny), cv::Point(maxx, cut_miny), cv::Scalar(200));
|
|
|
|
+ cv::line(tmp, cv::Point(minx, cut_midy), cv::Point(maxx, cut_midy), cv::Scalar(200));
|
|
|
|
+ cv::line(tmp, cv::Point(minx, cut_maxy), cv::Point(maxx, cut_maxy), cv::Scalar(200));
|
|
|
|
|
|
m_pImgCutPoint = mat2imginfo(tmp);
|
|
m_pImgCutPoint = mat2imginfo(tmp);
|
|
|
|
|
|
@@ -466,10 +490,82 @@ int CSolaCutPointReid::cut_point_reid(
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (m_pLogger) {
|
|
if (m_pLogger) {
|
|
- m_pLogger->INFO(m_imgId + " rootstock cut reid detect finished.");
|
|
|
|
|
|
+ if (m_stem_type == 0) {
|
|
|
|
+ m_pLogger->INFO(m_imgId + " sola scion cut reid detect finished.");
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ m_pLogger->INFO(m_imgId + " sola rootstock cut reid detect finished.");
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
};
|
|
};
|
|
|
|
+void CSolaCutPointReid::find_cut_ys(
|
|
|
|
+ vector<cv::Point>&points,
|
|
|
|
+ int&minx,int& maxx,
|
|
|
|
+ int&miny,int&maxy,
|
|
|
|
+ int&cut_miny, int&cut_midy, int&cut_maxy
|
|
|
|
+)
|
|
|
|
+{
|
|
|
|
+ //找到切口的y值
|
|
|
|
+
|
|
|
|
+ // 找到边框
|
|
|
|
+ minx = miny = 1000;
|
|
|
|
+ maxx = maxy = -1;
|
|
|
|
+ for (auto &pt : points) {
|
|
|
|
+ if (pt.x > maxx) { maxx = pt.x; }
|
|
|
|
+ if (pt.x < minx) { minx = pt.x; }
|
|
|
|
+ if (pt.y > maxy) { maxy = pt.y; }
|
|
|
|
+ if (pt.y < miny) { miny = pt.y; }
|
|
|
|
+ }
|
|
|
|
+ // 找到水平的边
|
|
|
|
+ std::vector<int> hist(maxy-miny+1,0);
|
|
|
|
+ std::vector<int> hist_x0(maxy - miny + 1, 1000);
|
|
|
|
+ std::vector<int> hist_x1(maxy - miny + 1, 0);
|
|
|
|
+ std::vector<int> hist_width(maxy - miny + 1, 0);
|
|
|
|
+
|
|
|
|
+ for (auto&pt : points) {
|
|
|
|
+ int idx = pt.y - miny;
|
|
|
|
+ hist.at(idx) += 1;
|
|
|
|
+ if (pt.x > hist_x1.at(idx)) {
|
|
|
|
+ hist_x1.at(idx) = pt.x;
|
|
|
|
+ }
|
|
|
|
+ if (pt.x < hist_x0.at(idx)) {
|
|
|
|
+ hist_x0.at(idx) = pt.x;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (int i = 0; i < hist.size(); ++i) {
|
|
|
|
+ hist_width.at(i) = hist_x1.at(i) - hist_x0.at(i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //计算茎的直径
|
|
|
|
+ std::vector<int> hist_width_copy(hist_width);
|
|
|
|
+ sort(hist_width_copy.begin(), hist_width_copy.end());
|
|
|
|
+ int pert_idx = int(0.98*hist_width_copy.size());
|
|
|
|
+ int stem_width = hist_width_copy.at(pert_idx);
|
|
|
|
+
|
|
|
|
+ int max_idx = max_element(hist.begin(), hist.end()) - hist.begin();
|
|
|
|
+ if (max_idx<int(hist.size() / 2.0)) {
|
|
|
|
+ //下锥,
|
|
|
|
+ std::vector<int> hist_width_rev;
|
|
|
|
+ for (int i = hist_width.size()-1; i >=0 ; i--) {
|
|
|
|
+ hist_width_rev.push_back(hist_width.at(i));
|
|
|
|
+ }
|
|
|
|
+ //在茎的指导下进行查找
|
|
|
|
+ int pos = trend_detect_pos(hist_width_rev, stem_width);
|
|
|
|
+ cut_miny = maxy - pos;
|
|
|
|
+ cut_maxy = maxy;
|
|
|
|
+ cut_midy = int((cut_miny + cut_maxy) / 2);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ //上锥,找到上锥点
|
|
|
|
+ int pos = trend_detect_pos(hist_width, stem_width);
|
|
|
|
+ cut_miny = miny;
|
|
|
|
+ cut_maxy = miny + pos;
|
|
|
|
+ cut_midy = int((cut_miny + cut_maxy) / 2);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
void CSolaCutPointReid::find_cut_curve(vector<cv::Point>&curve_points,
|
|
void CSolaCutPointReid::find_cut_curve(vector<cv::Point>&curve_points,
|
|
vector<cv::Point>&cut_curve, cv::RotatedRect& retval)
|
|
vector<cv::Point>&cut_curve, cv::RotatedRect& retval)
|
|
{
|
|
{
|
|
@@ -503,11 +599,18 @@ void CSolaCutPointReid::find_cut_curve(vector<cv::Point>&curve_points,
|
|
}
|
|
}
|
|
stem_width.push_back(line_max_x - line_min_x + 1);
|
|
stem_width.push_back(line_max_x - line_min_x + 1);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ //计算茎的直径
|
|
|
|
+ std::vector<int> hist_width_copy(stem_width);
|
|
|
|
+ sort(hist_width_copy.begin(), hist_width_copy.end());
|
|
|
|
+ int max_idx = int(0.98*hist_width_copy.size());
|
|
|
|
+ int max_stem_width = hist_width_copy.at(max_idx);
|
|
|
|
+
|
|
// find y range curve
|
|
// find y range curve
|
|
int min_yc = min_y;
|
|
int min_yc = min_y;
|
|
int max_yc = max_y;
|
|
int max_yc = max_y;
|
|
- if (m_stem_type == 0) {
|
|
|
|
- int pos = trend_detect_pos(stem_width, 15);
|
|
|
|
|
|
+ if (m_stem_type != 0) {//砧木
|
|
|
|
+ int pos = trend_detect_pos(stem_width, max_stem_width,15);
|
|
if (pos > 0) {
|
|
if (pos > 0) {
|
|
max_yc = min_yc + pos;
|
|
max_yc = min_yc + pos;
|
|
}
|
|
}
|
|
@@ -515,13 +618,13 @@ void CSolaCutPointReid::find_cut_curve(vector<cv::Point>&curve_points,
|
|
throw(m_imgId + " not found cut curve range");
|
|
throw(m_imgId + " not found cut curve range");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- else {
|
|
|
|
|
|
+ else { //接穗
|
|
vector<int> stem_width_r;
|
|
vector<int> stem_width_r;
|
|
vector<int>::reverse_iterator rit = stem_width.rbegin();
|
|
vector<int>::reverse_iterator rit = stem_width.rbegin();
|
|
for (; rit != stem_width.rend(); ++rit) {
|
|
for (; rit != stem_width.rend(); ++rit) {
|
|
stem_width_r.push_back(*rit);
|
|
stem_width_r.push_back(*rit);
|
|
}
|
|
}
|
|
- int pos = trend_detect_pos(stem_width_r, 15);
|
|
|
|
|
|
+ int pos = trend_detect_pos(stem_width_r, max_stem_width, 15);
|
|
if (pos > 0) {
|
|
if (pos > 0) {
|
|
min_yc = max_yc - pos;
|
|
min_yc = max_yc - pos;
|
|
}
|
|
}
|
|
@@ -554,10 +657,10 @@ void CSolaCutPointReid::find_cut_curve(vector<cv::Point>&curve_points,
|
|
}
|
|
}
|
|
string CSolaCutPointReid::get_stem_type_name() {
|
|
string CSolaCutPointReid::get_stem_type_name() {
|
|
if (m_stem_type == 0) {
|
|
if (m_stem_type == 0) {
|
|
- return string("solanaceae rootstock");
|
|
|
|
|
|
+ return string("solanaceae scion");
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- return string("solanaceae scion");
|
|
|
|
|
|
+ return string("solanaceae rootstock");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void CSolaCutPointReid::img_preprocess(cv::Mat&img)
|
|
void CSolaCutPointReid::img_preprocess(cv::Mat&img)
|