ROI 接口便捷修改
传入的图片截取ROI后再进入识别接口
(识别接口比ROI接口的函数参数少一个传入的ROI)
无点只有点集
返回双点集
//平直冷侧翅片
bool ImageProcessingTest::straightColdSideFin_ROI(cv::Mat img, cv::Rect ROI, std::vector<cv::Point>& topList, std::vector<cv::Point>& bottomList, cv::Mat & canvas, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);//top = cv::Point(0, 0);//bottom = cv::Point(0, 0);cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}result = straightColdSideFin(imgOriginal, topList, bottomList, canvas, debug);//调用识别算法if (debug) {for (int i = 0; i < topList.size(); i++) {cv::Point top = topList.at(i);top += ROI_tl;if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】\n", top.x, top.y);}for (int i = 0; i < bottomList.size(); i++) {cv::Point bottom = bottomList.at(i);bottom += ROI_tl;if (debug) printf("-------------------------------------****------ roiF bottom=【%d, %d】\n", bottom.x, bottom.y);}}//if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);//img.copyTo(canvas);x值和y值补上ROI左上点x和y//if (ROI_flag) {// if (Corner != cv::Point(0, 0))// {// Corner.x += ROI_tl.x;// Corner.y += ROI_tl.y;// }//}img.copyTo(canvas);//调试时注释掉if (result){cv::Point textP(6, 0);//演示用endRes = 1;for (int i = 0; i < topList.size(); i++) {topList.at(i) += ROI_tl;cv::Point top = topList.at(i);circle(canvas, top, 2, cv::Scalar(0, 69, 255), -1);cv::putText(canvas, to_string(i), top + textP, cv::FONT_HERSHEY_COMPLEX, 0.45, cv::Scalar(0, 69, 255), 1);//演示用}for (int i = 0; i < bottomList.size(); i++) {bottomList.at(i) += ROI_tl;cv::Point bottom = bottomList.at(i);circle(canvas, bottom, 2, cv::Scalar(255, 69, 0), -1);cv::putText(canvas, to_string(i), bottom + textP, cv::FONT_HERSHEY_COMPLEX, 0.45, cv::Scalar(255, 69, 0), 1);//演示用}printf("topList.size()=%d , bottomList.size()=%d \n", topList.size(), bottomList.size());cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) {if (debug) printf("topList.size()=%d , bottomList.size()=%d \n", topList.size(), bottomList.size());for (int i = 0; i < topList.size(); i++) {cv::Point top = topList.at(i);circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】\n", top.x, top.y);}for (int i = 0; i < bottomList.size(); i++) {cv::Point bottom = bottomList.at(i);circle(ROIcanvas, bottom, 3, cv::Scalar(255, 69, 0), 1);if (debug) printf("-------------------------------------****------ roiF bottom=【%d, %d】\n", bottom.x, bottom.y);}}//if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);//if (debug) circle(ROIcanvas, bottom, 3, cv::Scalar(0, 69, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);//if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI接口_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//平直冷侧翅片:straightColdSideFin_ROI
int main333() {bool flag = false;std::string filePath = "../img/straightColdSideFin/0616img";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(200, 0);cv::Point brP = cv::Point(950, 1024);std::vector<cv::Point> topList;std::vector<cv::Point> bottomList;cv::Mat canvas;ImageProcessingTest m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}vector<string> path_name;bool lianxu = false; //循环测试if (lianxu){string path = filePath + cv::format("\\Image_20230614160744823.png");//string path = filePath + cv::format("\\Image_20230609111800152.png");//string path = filePath + cv::format("\\Image_20230601143638388.png");//string path = filePath + cv::format("\\Image_20230601143505168.png");//string path = filePath + cv::format("\\Image_20230609113049539.png");cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);bool flag = m_ImageProcessing.straightColdSideFin_ROI(src, ROI, topList, bottomList, canvas, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {for (int i = 0; i < topList.size(); i++) {cv::Point top = topList.at(i);cout << "top = " << top.x << " " << top.y << endl;circle(canvas, top, 6, cv::Scalar(0, 69, 255), 1);}for (int i = 0; i < bottomList.size(); i++) {cv::Point bottom = bottomList.at(i);cout << "bottom = " << bottom.x << " " << bottom.y << endl;circle(canvas, bottom, 6, cv::Scalar(255, 69, 0), 1);}printf("topList.size()=%d , bottomList.size()=%d \n", topList.size(), bottomList.size());}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;//cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << endl;int time_start = clock();int time_end = clock();//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);bool flag = m_ImageProcessing.straightColdSideFin_ROI(src, ROI, topList, bottomList, canvas);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {for (int i = 0; i < topList.size(); i++) {cv::Point top = topList.at(i);cout << "top = " << top.x << " " << top.y << endl;}for (int i = 0; i < bottomList.size(); i++) {cv::Point bottom = bottomList.at(i);cout << "bottom = " << bottom.x << " " << bottom.y << endl;}printf("topList.size()=%d , bottomList.size()=%d \n", topList.size(), bottomList.size());}canvas.copyTo(src);//cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::waitKey(10);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;if (number == path_name.size()) break;}}cout << "main 循环结束!!!" << endl;ofs.close();cv::waitKey(0);system("Pause");return 0;
}
单点
返回只有单点
bool ImageProcess::arcPlusLine_ROI(cv::Mat img, cv::Rect ROI, cv::Point & top, cv::Mat & canvas, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}result = arcPlusLine(imgOriginal, top, canvas, debug);//调用识别算法if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】\n", top.x, top.y);//img.copyTo(canvas);//img.copyTo(canvas);//调试时注释掉cv::Mat t1;//canvas.convertTo(t1, -1, 900 / 100.0, 200 - 100);//第一次线性变换100canvas.convertTo(t1, -1, 900 / 100.0, 200 - 100);//第一次线性变换100if (debug)cv::imshow("线性变换ROI", t1);t1.copyTo(canvas);if (result){endRes = 1;top += ROI_tl;cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);int w = 38;int thickness = 4;cv::Point curPoint = top;cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(235, 135, 40), thickness);circle(canvas, top, 2, cv::Scalar(0, 69, 255), -1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】 \n", top.x, top.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);//cv::Rect roi_(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);//if(!ROI_flag) canvas.copyTo(canvas);//else canvas = canvas(roi_); //裁剪出的ROI区域return result;
}
调用main:
//圆弧+直线 内角:arcPlusLine_ROI
int main/*arcl*/() {bool flag = false;//std::string filePath = "E://vsproject//WeldingLine//1219img//in//宁波金波";//std::string filePath = "E://vsproject//WeldingLine//1219img//in//宁波金波//down";std::string filePath = "E://vsproject//WeldingLine//1219img//in//宁波金波//LogImg";//std::string filePath = "../img/ThreadedRoundPipe/0530img";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(200, 340);cv::Point brP = cv::Point(950, 999);cv::Point top(90, 90);cv::Mat canvas;VisualInterface m_ImageProcessing;//ImageProcess m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}vector<string> path_name;bool lineOnTop = true;bool getROI = !true;bool lianxu = false; //循环测试if (!lianxu){string name = cv::format("\\Img_2024_03_12_15_01_57_350_TYPE_12_ROI_486_64_257_474_src.png");string path = filePath + name;//string path = filePath + cv::format("\\Image_20240228115544906.bmp");cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);bool flag = m_ImageProcessing.arcPlusLine_ROI(src, ROI, top, canvas, lineOnTop, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 165), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){if (i.find("_res") != std::string::npos ) continue;if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.arcPlusLine_ROI(src, ROI, top, canvas, lineOnTop, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::waitKey(10);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;if (number == path_name.size()) break;}}cout << "main 循环结束!!!" << endl;ofs.close();cv::waitKey(0);system("Pause");return 0;
}
cv::Rect getROIFromString(std::string str) {//图像名字格式:“SrcImg_2023_10_11_11_39_19_002_ROI_600_396_137_218_src.png”if (str.empty()) return cv::Rect(0, 0, 0, 0);using namespace std;const char *split = "_";char *p = strtok((char*)str.c_str(), split);std::vector<char*>data;while (p != NULL) {cout << p << endl;data.push_back(p);p = strtok(NULL, split);}//9 12;if (data.size() < 12)return cv::Rect();return cv::Rect(atoi(data[data.size() - 5]),atoi(data[data.size() - 4]),atoi(data[data.size() - 3]),atoi(data[data.size() - 2]));//return cv::Rect(// atoi(data[9]),// atoi(data[10]),// atoi(data[11]),// atoi(data[12]));
}
返回只有单点,传入(高/低曝光图)两张原图,返回单点(高曝光图和激光图结合时使用)
int ImageProcess::getPnt_2Dwith3D_MaiSi(cv::Mat imgHE, cv::Mat imgLE, cv::Mat & canvas, cv::Point & resPoint, bool &MaiSi_isTopPnt, cv::Rect ROI, bool debug)
{int endRes = 0;bool result = false;imgHE.copyTo(canvas);cv::addWeighted(imgHE, 0.5, imgLE, 0.5, 0, canvas);ImageProcess pd;cv::Mat imgHE_roi;cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);cv::Mat img;imgLE.copyTo(img);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0)){img.copyTo(imgOriginal);imgHE.copyTo(imgHE_roi);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalimgHE_roi = imgHE(roi);ROI_flag = true;if (debug) {cv::Mat tmp;img.copyTo(tmp);rectangle(tmp, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) cv::imshow("根据roi裁剪后进入识别的图", tmp);}}result = getPnt_2Dwith3D_MaiSi(imgHE_roi, imgOriginal, canvas, resPoint, MaiSi_isTopPnt, debug);cv::addWeighted(imgHE, 0.5, imgLE, 0.5, 0, canvas);//x值和y值补上ROI左上点x和yif (ROI_flag){if (resPoint != cv::Point(0, 0)){resPoint.x += ROI_tl.x;resPoint.y += ROI_tl.y;}}if (debug) std::cout << img.size() << imgOriginal.size() << std::endl;if (result){endRes = 1;cv::circle(canvas, resPoint, 3, cv::Scalar(0, 0, 255), -1, 8, 0);putText(canvas, "true", { cv::Point(250, 250) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);//putText(canvas, "EmbWare_Leg", { cv::Point(250, 350) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);if (MaiSi_isTopPnt) {putText(canvas, "isTopPnt", { resPoint + cv::Point(15, 5) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(195, 165, 255), 1);}else {putText(canvas, "isBotPnt", { resPoint + cv::Point(15, 5) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(155, 155, 255), 1);}Mark(canvas);}else{putText(canvas, "false", { cv::Point(250, 250) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);Mark(canvas);}rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);return endRes;
}
返回单点+上下翻转再进入识别
/*//圆弧+直线 求内角cv::Mat img, 原图cv::Rect ROI,cv::Point& Corner, 输出角点cv::Mat &canvas,效果图可视化bool lineOnTop = true,直线部分是否为较上端的角边,true则为是,false反之*/bool arcPlusLine(cv::Mat imgOriginal, cv::Point& Corner, cv::Mat &canvas, bool debug = false);bool arcPlusLine_ROI(cv::Mat img, cv::Rect ROI, cv::Point& Corner, cv::Mat &canvas, bool lineOnTop = true, bool debug = false);
bool ImageProcess::arcPlusLine_ROI(cv::Mat img, cv::Rect ROI, cv::Point & top, cv::Mat & canvas, bool lineOnTop, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}if (lineOnTop) {result = arcPlusLine(imgOriginal, top, canvas, debug);//调用识别算法}else {cv::Mat fpMt;cv::flip(imgOriginal, fpMt, 0); // 上下翻转 x对称result = arcPlusLine(fpMt, top, canvas, debug);//调用识别算法if (result) {top.y = fpMt.rows - top.y - 1;}}cv::Mat lockCanvas = canvas.clone();if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】\n", top.x, top.y);//img.copyTo(canvas);//img.copyTo(canvas);//调试时注释掉//cv::Mat t1;//canvas.convertTo(t1, -1, 900 / 100.0, 200 - 100);//第一次线性变换100//if (debug)cv::imshow("线性变换ROI", t1);//t1.copyTo(canvas);if (result){endRes = 1;top += ROI_tl;cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);int w = 38;int thickness = 4;cv::Point curPoint = top;cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(235, 135, 40), thickness);circle(canvas, top, 2, cv::Scalar(0, 69, 255), -1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】 \n", top.x, top.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);//cv::Rect roi_(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);//if(!ROI_flag) canvas.copyTo(canvas);//else canvas = canvas(roi_); //裁剪出的ROI区域lockCanvas.copyTo(canvas);return result;
}
调用main:
// 内角:arcPlusLine_ROI
int main/*arcl*/() {bool flag = false;std::string filePath = "E://vsproject//WeldingLine//1219img//in//宁波金波";//std::string filePath = "E://vsproject//WeldingLine//1219img//in//宁波金波//down";//std::string filePath = "../img/ThreadedRoundPipe/0530img";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(200, 340);cv::Point brP = cv::Point(950, 999);cv::Point top(90, 90);cv::Mat canvas;//VisualInterface m_ImageProcessing;ImageProcess m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}vector<string> path_name;bool lineOnTop = true;bool lianxu = false; //循环测试if (lianxu){string path = filePath + cv::format("\\Image_20240304155500627.png");//string path = filePath + cv::format("\\Image_20240228115544906.bmp");cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);bool flag = m_ImageProcessing.arcPlusLine_ROI(src, ROI, top, canvas, lineOnTop, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 165), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);bool flag = m_ImageProcessing.arcPlusLine_ROI(src, ROI, top, canvas, lineOnTop, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::waitKey(10);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;if (number == path_name.size()) break;}}cout << "main 循环结束!!!" << endl;ofs.close();cv::waitKey(0);system("Pause");return 0;
}
返回单点+1个点集+上下翻转再进入识别
bool PTank_imgProcess::arcPlusLine_ROI(cv::Mat img, cv::Rect ROI, cv::Point & top, std::vector<cv::Point>& allPntList, cv::Mat & canvas, bool lineOnTop, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}cv::Mat lockCanvas;if (lineOnTop) {result = arcPlusLine(imgOriginal, top, allPntList, canvas, debug);//调用识别算法canvas.copyTo(lockCanvas);//for (int i = 0; i < allPntList.size(); i++) {// cv::line(lockCanvas, allPntList.at(i), cv::Point(allPntList.at(i).x - 3, allPntList.at(i).y), cv::Scalar(55, 195, 40), 1);//}}else {cv::Mat fpMt;cv::flip(imgOriginal, fpMt, 0); // 上下翻转 x对称result = arcPlusLine(fpMt, top, allPntList, canvas, debug);//调用识别算法canvas.copyTo(lockCanvas);if (result) {top.y = fpMt.rows - top.y - 1;for (int i = 0; i < allPntList.size(); i++) {//cv::line(lockCanvas, allPntList.at(i), cv::Point(allPntList.at(i).x - 3, allPntList.at(i).y), cv::Scalar(55, 195, 40), 1);allPntList.at(i).y = fpMt.rows - allPntList.at(i).y - 1;}}}if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】\n", top.x, top.y);//img.copyTo(canvas);//img.copyTo(canvas);//调试时注释掉//cv::Mat t1;//canvas.convertTo(t1, -1, 900 / 100.0, 200 - 100);//第一次线性变换100//if (debug)cv::imshow("线性变换ROI", t1);//t1.copyTo(canvas);if (result){img.copyTo(canvas);endRes = 1;top += ROI_tl;for (int i = 0; i < allPntList.size(); i++) {allPntList.at(i) += ROI_tl;}cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);int w = 38;int thickness = 4;cv::Point curPoint = top;cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(235, 135, 40), thickness);circle(canvas, top, 2, cv::Scalar(0, 69, 255), -1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);w = 3;for (int i = 0; i < allPntList.size(); i++) {cv::Point curPoint = allPntList.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(55, 195, 40), 1);}}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】 \n", top.x, top.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);//cv::Rect roi_(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);//if(!ROI_flag) canvas.copyTo(canvas);//else canvas = canvas(roi_); //裁剪出的ROI区域if (result) lockCanvas.copyTo(canvas);cv::putText(canvas, to_string(result), cv::Point(30, 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);return result;
}
调用main:
// 内角:arcPlusLine_ROI 类似金波(金波优化版)
int main/*arcl*/() {bool flag = false;//std::string filePath = "E://vsproject//压力罐\\img\\类金波/top";std::string filePath = "E://vsproject//压力罐\\img\\类金波";//std::string filePath = "E://vsproject//压力罐\\img\\叶子";//std::string filePath = "../img/ThreadedRoundPipe/0530img";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(200, 340);cv::Point brP = cv::Point(950, 999);cv::Point top(90, 90);std::vector<cv::Point> allPntList;cv::Mat canvas;PTank_imgProcess m_ImageProcessing;//ImageProcess m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}vector<string> path_name;bool lineOnTop = !true;bool getROI = true;bool lianxu = false; //循环测试if (!lianxu){string name = cv::format("\\Image_20240627151014832.png");string path = filePath + name;cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);bool flag = m_ImageProcessing.arcPlusLine_ROI(src, ROI, top, allPntList, canvas, lineOnTop, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 165), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){if (i.find("_res") != std::string::npos) continue;if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.arcPlusLine_ROI(src, ROI, top, allPntList, canvas, lineOnTop, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::waitKey(10);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;if (number == path_name.size()) break;}}cout << "main 循环结束!!!" << endl;ofs.close();cv::waitKey(0);system("Pause");return 0;
}
双点
返回只有双点
bool ImageProcessingTest::ThreadedRoundPipe_ROI(cv::Mat img, cv::Rect ROI, cv::Point& top, cv::Point& bottom, cv::Mat & canvas, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);bottom = cv::Point(0, 0);cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}result = ThreadedRoundPipe(imgOriginal, top, bottom, canvas, debug);//调用识别算法if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);//img.copyTo(canvas);x值和y值补上ROI左上点x和y//if (ROI_flag) {// if (Corner != cv::Point(0, 0))// {// Corner.x += ROI_tl.x;// Corner.y += ROI_tl.y;// }//}img.copyTo(canvas);//调试时注释掉cv::Mat t1;//canvas.convertTo(t1, -1, 900 / 100.0, 200 - 100);//第一次线性变换100canvas.convertTo(t1, -1, 900 / 100.0, 200 - 100);//第一次线性变换100if (debug)cv::imshow("线性变换ROI", t1);t1.copyTo(canvas);if (result){endRes = 1;top += ROI_tl;bottom += ROI_tl;cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);int w = 38;int thickness = 4;cv::Point curPoint = top;cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(235, 135, 40), thickness);curPoint = bottom;cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(235, 135, 40), thickness);circle(canvas, top, 2, cv::Scalar(0, 69, 255), -1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, bottom, 2, cv::Scalar(0, 69, 255), -1);circle(canvas, bottom, 43, cv::Scalar(255, 169, 0), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, bottom, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, bottom, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);//cv::Rect roi_(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);//if(!ROI_flag) canvas.copyTo(canvas);//else canvas = canvas(roi_); //裁剪出的ROI区域return result;
}
调用main:
//螺纹圆管:ThreadedRoundPipe_ROI
int main222() {bool flag = false;//std::string filePath = "E:\\vsproject\\勋仪交接\\标克艾芬达暖水管/0529img";//std::string filePath = "../img/ThreadedRoundPipe/0530img";std::string filePath = "../img/ThreadedRoundPipe/0606img";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(200, 340);cv::Point brP = cv::Point(950, 999);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Mat canvas;ImageProcessingTest m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}vector<string> path_name;bool lianxu = false; //循环测试if (!lianxu){//string path = filePath + cv::format("\\Image_20230606135229441.png");string path = filePath + cv::format("\\Image_20230606135308519.png");//string path = filePath + cv::format("\\Image_20230601143638388.png");//string path = filePath + cv::format("\\Image_20230601143505168.png");//string path = filePath + cv::format("\\Image_20230529095011455.png");cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);bool flag = m_ImageProcessing.ThreadedRoundPipe_ROI(src, ROI, top, bottom, canvas, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << endl;int time_start = clock();int time_end = clock();//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);bool flag = m_ImageProcessing.ThreadedRoundPipe_ROI(src, ROI, top, bottom, canvas, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::waitKey(10);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;if (number == path_name.size()) break;}}cout << "main 循环结束!!!" << endl;ofs.close();cv::waitKey(0);system("Pause");return 0;
}
返回双点+1个点集
/*//矩形位置 返回双点+骨干点集cv::Mat img, 原图cv::Rect ROI, cv::Point& top, 输出焊点(图像上位于较上方的点)cv::Point& bottom, 输出焊点(图像上位于较下方的点)std::vector<cv::Point>& allPntList:直线部分非弧线的点集cv::Mat &canvas,效果图可视化*/bool rectangle2Pnt(cv::Mat imgOriginal, cv::Point& top, cv::Point& bottom, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool debug = false);bool rectangle2Pnt_ROI(cv::Mat img, cv::Rect ROI, cv::Point& top, cv::Point& bottom, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool debug = false);
bool PTank_imgProcess::rectangle2Pnt_ROI(cv::Mat img, cv::Rect ROI, cv::Point & top, cv::Point & bottom, std::vector<cv::Point>& allPntList, cv::Mat & canvas, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);bottom = cv::Point(0, 0);allPntList.clear();cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}result = rectangle2Pnt(imgOriginal, top, bottom, allPntList, canvas, debug);//调用识别算法if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);//img.copyTo(canvas);img.copyTo(canvas);//调试时注释掉if (result){endRes = 1;top += ROI_tl;bottom += ROI_tl;for (int i = 0; i < allPntList.size(); i++) {allPntList.at(i) += ROI_tl;}int w = 5;for (int i = 0; i < allPntList.size(); i++) {cv::Point curPoint = allPntList.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(55, 195, 40), 1);}cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);circle(canvas, top, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, bottom, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 43, cv::Scalar(255, 169, 0), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, bottom, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, bottom, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//矩形位置 返回双点+骨干点集
int main/*Rectangle2Pnt_ROI*/() {bool flag;//std::string filePath = "../../../../Log08141641/TestImg/src";std::string filePath = "E://vsproject//压力罐\\img\\矩形";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(500, 292);cv::Point brP = cv::Point(750, 677);//cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(539, 218, 113, 513);cv::Point top(90, 90);cv::Point bottom(90, 90);int outMidY;cv::Mat canvas;PTank_imgProcess m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}std::vector<cv::Point> allPntList;vector<string> path_name;bool getROI = true;bool lianxu = false; //循环测试if (!lianxu){string name = cv::format("\\Image_20240627144421072.png");string path = filePath + name;cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);bool flag = m_ImageProcessing.rectangle2Pnt_ROI(src, ROI, top, bottom, allPntList, canvas, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::RECURS_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find(".log") != std::string::npos) continue;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.rectangle2Pnt_ROI(src, ROI, top, bottom, allPntList, canvas, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(10);}cout << "循环结束!!! main " << endl;}ofs.close();cv::waitKey(0);system("Pause");return 0;
}
返回双点+三点集+左右/上下翻转再进入识别
注:该接口中 bottom, linearPntB无效!!!
根据传入参数判断是否左右翻转,判断识别的是上半部分还是下半部分,下半部分则需再做上下翻转再进入识别。
/*//D型主管,方形支管 只处理上半部分或下半部分cv::Mat img, 原图cv::Rect ROI, 可以让右边的干扰直反光落进去,上下不用截,左右可适当截小一下减少识别时的计算时间std::vector<cv::Point>& linearPnt:直线部分非弧线的点集cv::Point& top, 输出焊点(图像上位于较上方的点)倒角弧形边边上的激光最边边点cv::Point& bottom, 输出焊点(图像上位于较下方的点)倒角弧形边边上的激光最边边点cv::Mat &canvas,效果图可视化bool arcTop_right = true;//圆弧顶点是否朝右的标志量,默认为true(true为朝右,false为朝左)bool isTopHalf = true;//识别区域是否为上半部分,上半部分为true,下半部分反之注:该接口中 bottom, linearPntB无效!!!*/bool OneSideSquare(cv::Mat imgOriginal, std::vector<cv::Point>& linearPntT, std::vector<cv::Point>& linearPntB, std::vector<cv::Point>& linearPntM, cv::Point& top, cv::Point& bottom, cv::Mat &canvas, bool debug = false);bool OneSideSquare_ROI(cv::Mat img, cv::Rect ROI, std::vector<cv::Point>& linearPntT, std::vector<cv::Point>& linearPntB, std::vector<cv::Point>& linearPntM, cv::Point& top, cv::Point& bottom, cv::Mat &canvas, bool arcTop_right = true, bool isTopHalf = true, bool debug = false);
bool ImageProcessing::OneSideSquare_ROI(cv::Mat img, cv::Rect ROI, std::vector<cv::Point>& linearPntT, std::vector<cv::Point>& linearPntB, std::vector<cv::Point>& linearPntM, cv::Point & top, cv::Point & bottom, cv::Mat & canvas, bool arcTop_right, bool isTopHalf, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);bottom = cv::Point(0, 0);linearPntT.clear();linearPntB.clear();linearPntM.clear();cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}if (arcTop_right) {//圆弧顶点朝右的情况if (isTopHalf) {result = OneSideSquare(imgOriginal, linearPntT, linearPntB, linearPntM, top, bottom, canvas, debug);//调用识别算法}else {cv::Mat fpMt;cv::flip(imgOriginal, fpMt, 0); // 上下翻转 x对称result = OneSideSquare(fpMt, linearPntT, linearPntB, linearPntM, top, bottom, canvas, debug);//调用识别算法if (result) {top.y = fpMt.rows - top.y - 1;for (int i = 0; i < linearPntT.size(); i++) {linearPntT.at(i).y = fpMt.rows - linearPntT.at(i).y - 1;}for (int i = 0; i < linearPntM.size(); i++) {linearPntM.at(i).y = fpMt.rows - linearPntM.at(i).y - 1;}}}}else {//圆弧顶点朝左的情况cv::Mat flipMat;cv::flip(imgOriginal, flipMat, 1); // 左右翻转 y对称if (debug) imshow("图像左右翻转", flipMat);if (isTopHalf) {result = OneSideSquare(flipMat, linearPntT, linearPntB, linearPntM, top, bottom, canvas, debug);//调用识别算法}else {cv::Mat fpMt;cv::flip(flipMat, fpMt, 0); // 上下翻转 x对称result = OneSideSquare(fpMt, linearPntT, linearPntB, linearPntM, top, bottom, canvas, debug);//调用识别算法if (result) {top.y = fpMt.rows - top.y - 1;for (int i = 0; i < linearPntT.size(); i++) {linearPntT.at(i).y = fpMt.rows - linearPntT.at(i).y - 1;}for (int i = 0; i < linearPntM.size(); i++) {linearPntM.at(i).y = fpMt.rows - linearPntM.at(i).y - 1;}}}if (result) {top.x = flipMat.cols - top.x - 1;//bottom.x = flipMat.cols - bottom.x - 1;for (int i = 0; i < linearPntT.size(); i++) {linearPntT.at(i).x = flipMat.cols - linearPntT.at(i).x - 1;}for (int i = 0; i < linearPntB.size(); i++) {linearPntB.at(i).x = flipMat.cols - linearPntB.at(i).x - 1;}for (int i = 0; i < linearPntM.size(); i++) {linearPntM.at(i).x = flipMat.cols - linearPntM.at(i).x - 1;}}}if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);//img.copyTo(canvas);x值和y值补上ROI左上点x和y//if (ROI_flag) {// if (Corner != cv::Point(0, 0))// {// Corner.x += ROI_tl.x;// Corner.y += ROI_tl.y;// }//}img.copyTo(canvas);//调试时注释掉if (result){endRes = 1;top += ROI_tl;//bottom += ROI_tl;for (int i = 0; i < linearPntT.size(); i++) {linearPntT.at(i) += ROI_tl;}for (int i = 0; i < linearPntB.size(); i++) {linearPntB.at(i) += ROI_tl;}for (int i = 0; i < linearPntM.size(); i++) {linearPntM.at(i) += ROI_tl;}for (int i = 0; i < linearPntT.size(); i++) {cv::Point curPoint = linearPntT.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - 5, curPoint.y), cv::Scalar(55, 195, 40), 1);}for (int i = 0; i < linearPntB.size(); i++) {cv::Point curPoint = linearPntB.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - 5, curPoint.y), cv::Scalar(55, 195, 40), 1);}for (int i = 0; i < linearPntM.size(); i++) {cv::Point curPoint = linearPntM.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - 5, curPoint.y), cv::Scalar(145, 175, 40), 1);}cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);circle(canvas, top, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);//circle(canvas, bottom, 3, cv::Scalar(0, 69, 255), 1);//circle(canvas, bottom, 43, cv::Scalar(255, 169, 0), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);//if (debug) circle(ROIcanvas, bottom, 3, cv::Scalar(0, 69, 255), 1);//if (debug) circle(ROIcanvas, bottom, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//D型主管,方形支管 上或下单侧 OneSideSquare_ROI
int main() {bool flag;//std::string filePath = "../../../../0方管支管/1023img";std::string filePath = "../../../../0方管支管/left";//std::string filePath = "../../../../0方管支管/right";string resPath = "/output";//string resPath = filePath + "./output";//cv::Point tlP = cv::Point(500, 40);//cv::Point brP = cv::Point(750, 777);cv::Point tlP = cv::Point(584, 236);cv::Point brP = cv::Point(660, 820);//cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(639, 188, 125, 569);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Point2f midP(90, 90);int outMidY;cv::Mat canvas;ImageProcessing m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}std::vector<cv::Point> linearPntT;std::vector<cv::Point> linearPntB;std::vector<cv::Point> linearPntM;vector<Picture_set> img_buf;vector<string> path_name;bool arcTop_right = !true;bool isTopHalf = true;int midyTolerant = 4;bool getROI = true;bool lianxu = false; //循环测试if (lianxu){//string path = filePath + cv::format("\\Image_20231023105829348.png");//std::string name = cv::format("\\ImgD_2023_10_26_10_48_12_135_567_196_153_603_Src.png");std::string name = cv::format("\\ImgD_2023_10_25_18_16_24_519_569_200_166_559_Src.png");string path = filePath + name;cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::NORMCONV_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) {ROI = getROIFromString(name);ROI.height /= 2;if (!isTopHalf) {ROI.y += ROI.height;}}//鼠标点击的坐标【691, 319】// 鼠标点击的坐标【692, 632】//cout << src.size() << endl;//rotateImage(src);//cout << src.size() << endl;//鼠标点击的坐标【707, 691】// 鼠标点击的坐标【395, 691】//trueX=outY;//trueY=oriSrc.rows-outX;//circle(src, cv::Point(622, 424), 5, cv::Scalar(255, 255, 255), -1);//cv::Mat flipMat;//cv::flip(src, flipMat, 1);//cv::Point q = cv::Point(flipMat.cols - 622 - 1, 424)/* - cv::Point(546, 228)*/;//circle(flipMat, q, 3, cv::Scalar(0, 0, 0), -1);//cv::imshow("flipMat", flipMat);//cv::waitKey();//cv::flip(src, src, 0);bool flag = m_ImageProcessing.OneSideSquare_ROI(src, ROI, linearPntT, linearPntB, linearPntM, top, bottom, canvas, arcTop_right, isTopHalf, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::RECURS_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find(".log") != std::string::npos) continue;if (i.find(".txt") != std::string::npos) continue;std::string name = i;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) {ROI = getROIFromString(name);ROI.height /= 2;if (!isTopHalf) {ROI.y += ROI.height;}}bool flag = m_ImageProcessing.OneSideSquare_ROI(src, ROI, linearPntT, linearPntB, linearPntM, top, bottom, canvas, arcTop_right, isTopHalf, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(10);}cout << "循环结束!!! main " << endl;}ofs.close();cv::waitKey(0);system("Pause");return 0;
}
三点
返回三点+1个点集
/*//两弧线夹圆弧 返回三点+骨干点集cv::Mat img, 原图cv::Rect ROI,cv::Point& top, 输出焊点(图像上位于较上方的点)cv::Point& bottom, 输出焊点(图像上位于较下方的点)cv::Point2f& midP, 圆弧中点std::vector<cv::Point>& allPntList:直线部分非弧线的点集cv::Mat &canvas,效果图可视化*/bool twoArcsClipTheArc(cv::Mat imgOriginal, cv::Point& top, cv::Point& bottom, cv::Point2f& midP, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool debug = false);bool twoArcsClipTheArc_ROI(cv::Mat img, cv::Rect ROI, cv::Point& top, cv::Point& bottom, cv::Point2f& midP, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool arcTop_right = true, bool debug = false);
bool PTank_imgProcess::twoArcsClipTheArc_ROI(cv::Mat img, cv::Rect ROI, cv::Point & top, cv::Point & bottom, cv::Point2f & midP, std::vector<cv::Point>& allPntList, cv::Mat & canvas, bool arcTop_right, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);bottom = cv::Point(0, 0);midP = cv::Point2f(0, 0);allPntList.clear();cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}if (arcTop_right) {//圆弧顶点朝右的情况result = twoArcsClipTheArc(imgOriginal, top, bottom, midP, allPntList, canvas, debug);//调用识别算法}else {//圆弧顶点朝左的情况cv::Mat flipMat;cv::flip(imgOriginal, flipMat, 1); // 左右翻转 y对称if (debug) imshow("图像左右翻转", flipMat);result = twoArcsClipTheArc(flipMat, top, bottom, midP, allPntList, canvas, debug);//调用识别算法if (result) {top.x = flipMat.cols - top.x - 1;bottom.x = flipMat.cols - bottom.x - 1;for (int i = 0; i < allPntList.size(); i++) {allPntList.at(i).x = flipMat.cols - allPntList.at(i).x - 1;}if (midP != cv::Point2f(0, 0)) midP.x = flipMat.cols - midP.x - 1;}}if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) printf(" roiF midP=【%f, %f】\n", midP.x, midP.y);//img.copyTo(canvas);//img.copyTo(canvas);//调试时注释掉if (result){endRes = 1;for (int i = 0; i < allPntList.size(); i++) {allPntList.at(i) += ROI_tl;}for (int i = 0; i < allPntList.size(); i++) {cv::Point curPoint = allPntList.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - 5, curPoint.y), cv::Scalar(55, 195, 40), 1);}top += ROI_tl;bottom += ROI_tl;midP += cv::Point2f(ROI_tl);//if (midP != cv::Point2f(0, 0)) {// midP.x = midP.x + ROI_tl.x;// midP.y = midP.y + ROI_tl.y;//}circle(canvas, midP, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, midP, 43, cv::Scalar(0, 169, 255), 1);cv::line(canvas, midP, cv::Point2f(5, midP.y), cv::Scalar(155, 195, 40), 1);cv::line(canvas, cv::Point2f(midP.x, midP.y - 5), cv::Point2f(midP.x, midP.y + 5), cv::Scalar(155, 195, 40), 1);cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);circle(canvas, top, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, bottom, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 43, cv::Scalar(255, 169, 0), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, bottom, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, bottom, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) printf(" roiF midP=【%f, %f】\n", midP.x, midP.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//两弧线夹圆弧 返回三点+骨干点集
int main/*TwoArcsClipTheArc*/() {bool flag;std::string filePath = "../../img/圆弧夹圆弧";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(500, 292);cv::Point brP = cv::Point(750, 677);//cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(539, 218, 113, 513);cv::Rect ROI = cv::Rect(546, 228, 101, 520);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Point2f midP(90, 90);int outMidY;cv::Mat canvas;PTank_imgProcess m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}std::vector<cv::Point> allPntList;vector<string> path_name;bool arcTop_right = true;bool getROI = true;bool lianxu = false; //循环测试if (!lianxu){string name = cv::format("\\Image_20240702114054217.png");//string name = cv::format("\\Image_20240702170558613.png");//斜//string name = cv::format("\\Image_20240702170644641.png");//斜string path = filePath + name;//string path = filePath + cv::format("\\ImgD_2023_08_17_15_06_45_412_639_188_125_569_Src.png");cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::NORMCONV_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);bool flag = m_ImageProcessing.twoArcsClipTheArc_ROI(src, ROI, top, bottom, midP, allPntList, canvas, arcTop_right, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;cout << "midP = " << midP.x << " " << midP.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::RECURS_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find(".log") != std::string::npos) continue;if (i.find(".txt") != std::string::npos) continue;if (i.find("_result") != std::string::npos) continue;if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.twoArcsClipTheArc_ROI(src, ROI, top, bottom, midP, allPntList, canvas, arcTop_right, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(10);}cout << "循环结束!!! main " << endl;}ofs.close();cv::waitKey(0);system("Pause");return 0;
}
返回三点+双点集+左右翻转再进入识别
左右翻转变回来后必须要x-1,不然会与原来基于原图上的坐标对应不上。
/*//D型管的两直线夹圆弧//周六新策略:两边直线中间圆弧,激光平行于主管 (__O__两端直线中间半圆弧找圆弧的两端拐点)---圆轨迹cv::Mat img, 原图cv::Rect ROI, 可以让右边的干扰直反光落进去,上下不用截,左右可适当截小一下减少识别时的计算时间int outMidY,因y偏差过大时返回的两点无效,则返回圆弧区域的中心ycv::Point& midP, outMidY对应的圆弧上的骨干点(midP为(0,0)时,该值无效)std::vector<cv::Point>& linearPnt:直线部分非弧线的点集cv::Point& top, 输出焊点(图像上位于较上方的点)cv::Point& bottom, 输出焊点(图像上位于较下方的点)cv::Mat &canvas,效果图可视化int midyTolerant = 2;//outMidY的容差范围bool arcTop_right = true;//圆弧顶点是否朝右的标志量,默认为true(true为朝右,false为朝左)*/bool LaserParallelToTheMainD(cv::Mat imgOriginal, int &outMidY, cv::Point2f& midP, std::vector<cv::Point>& linearPntT, std::vector<cv::Point>& linearPntB, cv::Point& top, cv::Point& bottom, cv::Mat &canvas, int midyTolerant, bool debug = false);bool LaserParallelToTheMainD_ROI(cv::Mat img, cv::Rect ROI, int &outMidY, cv::Point2f& midP, std::vector<cv::Point>& linearPntT, std::vector<cv::Point>& linearPntB, cv::Point& top, cv::Point& bottom, cv::Mat &canvas, int midyTolerant = 2, bool arcTop_right = true, bool debug = false);
bool ImageProcessing::LaserParallelToTheMainD_ROI(cv::Mat img, cv::Rect ROI, int &outMidY, cv::Point2f& midP, std::vector<cv::Point>& linearPntT, std::vector<cv::Point>& linearPntB, cv::Point & top, cv::Point & bottom, cv::Mat & canvas, int midyTolerant, bool arcTop_right, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);bottom = cv::Point(0, 0);midP = cv::Point2f(0, 0);linearPntT.clear();linearPntB.clear();outMidY = 0;cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}if (arcTop_right) {//圆弧顶点朝右的情况result = LaserParallelToTheMainD(imgOriginal, outMidY, midP, linearPntT, linearPntB, top, bottom, canvas, midyTolerant, debug);//调用识别算法}else {//圆弧顶点朝左的情况cv::Mat flipMat;cv::flip(imgOriginal, flipMat, 1); // 左右翻转 y对称if (debug) imshow("图像左右翻转", flipMat);result = LaserParallelToTheMainD(flipMat, outMidY, midP, linearPntT, linearPntB, top, bottom, canvas, midyTolerant, debug);//调用识别算法if (result) {top.x = flipMat.cols - top.x - 1;bottom.x = flipMat.cols - bottom.x - 1;for (int i = 0; i < linearPntT.size(); i++) {linearPntT.at(i).x = flipMat.cols - linearPntT.at(i).x - 1;}for (int i = 0; i < linearPntB.size(); i++) {linearPntB.at(i).x = flipMat.cols - linearPntB.at(i).x - 1;}if (midP != cv::Point2f(0, 0)) midP.x = flipMat.cols - midP.x - 1;}}if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) printf(" roiF midP=【%f, %f】\n", midP.x, midP.y);//img.copyTo(canvas);x值和y值补上ROI左上点x和y//if (ROI_flag) {// if (Corner != cv::Point(0, 0))// {// Corner.x += ROI_tl.x;// Corner.y += ROI_tl.y;// }//}img.copyTo(canvas);//调试时注释掉if (result){endRes = 1;top += ROI_tl;bottom += ROI_tl;if (midP != cv::Point2f(0, 0)) {midP.x = midP.x + ROI_tl.x;midP.y = midP.y + ROI_tl.y;}cv::line(canvas, midP, cv::Point2f(5, midP.y), cv::Scalar(55, 195, 40), 1);cv::line(canvas, cv::Point2f(midP.x, midP.y - 5), cv::Point2f(midP.x, midP.y + 5), cv::Scalar(55, 195, 40), 1);for (int i = 0; i < linearPntT.size(); i++) {linearPntT.at(i) += ROI_tl;}for (int i = 0; i < linearPntB.size(); i++) {linearPntB.at(i) += ROI_tl;}for (int i = 0; i < linearPntT.size(); i++) {cv::Point curPoint = linearPntT.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - 5, curPoint.y), cv::Scalar(55, 195, 40), 1);}for (int i = 0; i < linearPntB.size(); i++) {cv::Point curPoint = linearPntB.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - 5, curPoint.y), cv::Scalar(55, 195, 40), 1);}cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);circle(canvas, top, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, bottom, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 43, cv::Scalar(255, 169, 0), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, bottom, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, bottom, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) printf(" roiF midP=【%f, %f】\n", midP.x, midP.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//CXL 两边直线中间圆弧,激光平行于主管 DDDDDDDDDDDDDDDDD 圆轨迹 增加直线部分点集 的重载
int main() {bool flag;std::string filePath = "../../../../Log08141641/TestImg/src";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(500, 292);cv::Point brP = cv::Point(750, 677);//cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(539, 218, 113, 513);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Point2f midP(90, 90);int outMidY;cv::Mat canvas;ImageProcessing m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}std::vector<cv::Point> linearPntT;std::vector<cv::Point> linearPntB;vector<string> path_name;bool arcTop_right = !true;int midyTolerant = 4;bool getROI = true;bool lianxu = false; //循环测试if (!lianxu){string name = cv::format("\\ImgD_2024_06_04_09_14_48_111_565_82_86_851_Src.png");string path = filePath + name;//string path = filePath + cv::format("\\ImgD_2023_08_17_15_06_45_412_639_188_125_569_Src.png");cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::NORMCONV_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);//trueX=outY;//trueY=oriSrc.rows-outX;//circle(src, cv::Point(622, 424), 5, cv::Scalar(255, 255, 255), -1);//cv::Mat flipMat;//cv::flip(src, flipMat, 1);//cv::Point q = cv::Point(flipMat.cols - 622 - 1, 424)/* - cv::Point(546, 228)*/;//circle(flipMat, q, 3, cv::Scalar(0, 0, 0), -1);//cv::imshow("flipMat", flipMat);//cv::waitKey();bool flag = m_ImageProcessing.LaserParallelToTheMainD_ROI(src, ROI, outMidY, midP, linearPntT, linearPntB, top, bottom, canvas, midyTolerant, arcTop_right, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::RECURS_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find(".log") != std::string::npos) continue;if (i.find(".txt") != std::string::npos) continue;if (i.find("_result") != std::string::npos) continue;if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.LaserParallelToTheMainD_ROI(src, ROI, outMidY, midP, linearPntT, linearPntB, top, bottom, canvas, midyTolerant, arcTop_right, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(10);}cout << "循环结束!!! main " << endl;}ofs.close();cv::waitKey(0);system("Pause");return 0;
}
四点
返回四点+1个点集
/*//矩形位置 返回四点+骨干点集cv::Mat img, 原图cv::Rect ROI,cv::Point & p1, 图像较上方的主管底部点cv::Point & p2, 图像较上方的矩形顶部边缘点cv::Point & p3, 图像较下方的主管底部点cv::Point & p4,图像较下方的矩形顶部边缘点std::vector<cv::Point>& allPntList:直线部分非弧线的点集cv::Mat &canvas,效果图可视化*/bool rectangle4Pnt(cv::Mat imgOriginal, cv::Point & p1, cv::Point& p2, cv::Point & p3, cv::Point& p4, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool debug = false);bool rectangle4Pnt_ROI(cv::Mat img, cv::Rect ROI, cv::Point & p1, cv::Point& p2, cv::Point & p3, cv::Point& p4, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool debug = false);
bool PTank_imgProcess::rectangle4Pnt_ROI(cv::Mat img, cv::Rect ROI, cv::Point & p1, cv::Point& p2, cv::Point & p3, cv::Point& p4, std::vector<cv::Point>& allPntList, cv::Mat & canvas, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);p1 = cv::Point(0, 0);p2 = cv::Point(0, 0);p3 = cv::Point(0, 0);p4 = cv::Point(0, 0);allPntList.clear();cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}result = rectangle4Pnt(imgOriginal, p1, p2, p3, p4, allPntList, canvas, debug);//调用识别算法if (debug) printf("-------------------------------------****------ roiF p1=【%d, %d】, p2=【%d, %d】\n", p1.x, p1.y, p2.x, p2.y);if (debug) printf("-------------------------------------****------ roiF p3=【%d, %d】, p4=【%d, %d】\n", p3.x, p3.y, p4.x, p4.y);//img.copyTo(canvas);img.copyTo(canvas);//调试时注释掉if (result){endRes = 1;p1 += ROI_tl;p2 += ROI_tl;p3 += ROI_tl;p4 += ROI_tl;for (int i = 0; i < allPntList.size(); i++) {allPntList.at(i) += ROI_tl;}int w = 5;for (int i = 0; i < allPntList.size(); i++) {cv::Point curPoint = allPntList.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(55, 195, 40), 1);}cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);circle(canvas, p1, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p1, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, p2, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p2, 43, cv::Scalar(255, 169, 0), 1);circle(canvas, p3, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p3, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, p4, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p4, 43, cv::Scalar(255, 169, 0), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, p1, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p1, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, p2, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p2, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, p3, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p3, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, p4, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p4, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("---------------****------ roiF p1=【%d, %d】, p2=【%d, %d】\n", p1.x, p1.y, p2.x, p2.y);if (debug) printf("---------------****------ roiF p3=【%d, %d】, p4=【%d, %d】\n", p3.x, p3.y, p4.x, p4.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//矩形位置 返回四点+骨干点集
int main/*Rectangle4Pnt_ROI*/() {bool flag;//std::string filePath = "../../../../Log08141641/TestImg/src";std::string filePath = "E://vsproject//压力罐\\img\\矩形";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(500, 292);cv::Point brP = cv::Point(750, 677);//cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(539, 218, 113, 513);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Point p3(90, 90);cv::Point p4(90, 90);int outMidY;cv::Mat canvas;PTank_imgProcess m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}std::vector<cv::Point> allPntList;vector<string> path_name;bool getROI = true;bool lianxu = false; //循环测试if (lianxu){string name = cv::format("\\Image_20240627144521008.png");string path = filePath + name;cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);bool flag = m_ImageProcessing.rectangle4Pnt_ROI(src, ROI, top, bottom, p3, p4, allPntList, canvas, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::RECURS_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find(".log") != std::string::npos) continue; if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.rectangle4Pnt_ROI(src, ROI, top, bottom, p3, p4, allPntList, canvas, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(10);}cout << "循环结束!!! main " << endl;}ofs.close();cv::waitKey(0);system("Pause");return 0;
}
返回四点+双点集
/*//多层多道焊 圆管表面 & 四边形坡口拼接cv::Mat img, 原图cv::Point& top, 输出焊点(图像上位于较上方的点)cv::Point& bottom, 输出焊点(图像上位于较下方的点)std::vector<cv::Point>& groovePnt:坡口部分包括内侧面的点集cv::Point& valleyT, 位于焊道底部的焊点(图像上位于较上方的点)cv::Point& valleyB, 位于焊道底部的焊点(图像上位于较下方的点)std::vector<cv::Point>& valleyPnt,位于焊道底部的,焊道底部两点之间的点集cv::Mat &canvas,效果图可视化cv::Rect ROI,*/bool multilayerMultichannel4(cv::Mat imgOriginal, cv::Point& top, cv::Point& bottom, std::vector<cv::Point>& groovePnt, cv::Point& valleyT, cv::Point& valleyB, std::vector<cv::Point>& valleyPnt, cv::Mat &canvas, bool debug = false);bool multilayerMultichannel4_ROI(cv::Mat img, cv::Point& top, cv::Point& bottom, std::vector<cv::Point>& groovePnt, cv::Point& valleyT, cv::Point& valleyB, std::vector<cv::Point>& valleyPnt, cv::Mat &canvas, cv::Rect ROI = cv::Rect(540, 540, 200, 200), bool debug = false);
bool ImageProcess::multilayerMultichannel4_ROI(cv::Mat img, cv::Point & top, cv::Point & bottom, std::vector<cv::Point>& groovePnt, cv::Point & valleyT, cv::Point & valleyB, std::vector<cv::Point>& valleyPnt, cv::Mat & canvas, cv::Rect ROI, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);top = cv::Point(0, 0);bottom = cv::Point(0, 0);groovePnt.clear();valleyT = cv::Point(0, 0);valleyB = cv::Point(0, 0);valleyPnt.clear();cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}result = multilayerMultichannel4(imgOriginal, top, bottom, groovePnt, valleyT, valleyB, valleyPnt, canvas, debug);//调用识别算法if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) printf("----- roiF valleyT=【%d, %d】, valleyB=【%d, %d】\n", valleyT.x, valleyT.y, valleyB.x, valleyB.y);//img.copyTo(canvas);x值和y值补上ROI左上点x和y//if (ROI_flag) {// if (Corner != cv::Point(0, 0))// {// Corner.x += ROI_tl.x;// Corner.y += ROI_tl.y;// }//}img.copyTo(canvas);//调试时注释掉cv::Mat t1;canvas.convertTo(t1, -1, 1900 / 100.0, 100 - 100);//第一次线性变换100if (debug)cv::imshow("线性变换ROI", t1);t1.copyTo(canvas);if (result){endRes = 1;top += ROI_tl;bottom += ROI_tl;valleyT += ROI_tl;valleyB += ROI_tl;for (int i = 0; i < groovePnt.size(); i++) {groovePnt.at(i) += ROI_tl;}for (int i = 0; i < valleyPnt.size(); i++) {valleyPnt.at(i) += ROI_tl;}int w = 9;for (int i = 0; i < groovePnt.size(); i++) {cv::Point curPoint = groovePnt.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x + w, curPoint.y), cv::Scalar(55, 195, 40), 1);}cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);circle(canvas, top, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, top, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, bottom, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 43, cv::Scalar(255, 169, 0), 1);circle(canvas, valleyT, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, valleyT, 43, cv::Scalar(0, 169, 255), 1);circle(canvas, valleyB, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, valleyB, 23, cv::Scalar(255, 169, 0), 1);for (int i = 0; i < valleyPnt.size(); i++) {cv::Point curPoint = valleyPnt.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(75, 155, 40), 1);}}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, top, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, top, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, bottom, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, bottom, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);if (debug) printf("----- roiF valleyT=【%d, %d】, valleyB=【%d, %d】\n", valleyT.x, valleyT.y, valleyB.x, valleyB.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//multilayerMultichannel4_ROI 多层多道焊 圆管表面 & 四边形坡口拼接
int main() {bool flag;//std::string filePath = "E:\\vsproject\\WeldingLine\\多层多道4";std::string filePath = "E:\\vsproject\\WeldingLine\\多层多道4\\TestImgAAA";std::string resPath = "/output";//string resPath = filePath + "./output";//cv::Point tlP = cv::Point(500, 40);//cv::Point brP = cv::Point(750, 777);cv::Point tlP = cv::Point(345, 108);cv::Point brP = cv::Point(859, 951);cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(544,208,107,545);//cv::Rect ROI = cv::Rect(639, 188, 125, 569);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Point valleyT(90, 90);cv::Point valleyB(90, 90);int outMidY;cv::Mat canvas;VisualInterface m_ImageProcessing;//ImageProcess m_ImageProcessing;std::vector<cv::Point> groovePnt;std::vector<cv::Point> valleyPnt;vector<string> path_name;bool arcTop_right = true;int midyTolerant = 4;bool getROI = !true;bool lianxu = false; //循环测试if (!lianxu){string name = cv::format("\\SrcImg_2023_12_28_14_57_17_133_ROI_1132_999_401_126_src.png");//中间底部较高的情况string path = filePath + name;cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::NORMCONV_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//ROI = cv::Rect(400, 0, 400, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);bool flag = m_ImageProcessing.multilayerMultichannel4_ROI(src, top, bottom, groovePnt, valleyT, valleyB, valleyPnt, canvas, ROI, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::RECURS_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find(".log") != std::string::npos) continue;if (i.find(".txt") != std::string::npos) continue;if (i.find("_result") != std::string::npos) continue;if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//ROI = cv::Rect(400, 0, 400, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.multilayerMultichannel4_ROI(src, top, bottom, groovePnt, valleyT, valleyB, valleyPnt, canvas, ROI, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(10);}cout << "循环结束!!! main " << endl;}cv::waitKey(0);system("Pause");return 0;
}
五点
返回五点+1个点集
/*//两弧线夹悬空的圆弧 返回五点+骨干点集 定"L"型管相贯线水平用cv::Mat img, 原图cv::Rect ROI,cv::Point & p1, 图像较上方的主管底部点cv::Point & p2, 图像较上方的弧形激光边缘点cv::Point2f & midP, 圆弧中点cv::Point & p3, 图像较下方的弧形激光边缘点cv::Point & p4,图像较下方的主管底部点std::vector<cv::Point>& allPntList:直线部分非弧线的点集cv::Mat &canvas,效果图可视化*/bool twoArcsClipTheHangingArc(cv::Mat imgOriginal, cv::Point & p1, cv::Point& p2, cv::Point2f& midP, cv::Point& p3, cv::Point& p4, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool debug = false);bool twoArcsClipTheHangingArc_ROI(cv::Mat img, cv::Rect ROI, cv::Point& p1, cv::Point& p2, cv::Point2f& midP, cv::Point& p3, cv::Point& p4, std::vector<cv::Point>& allPntList, cv::Mat &canvas, bool debug = false);
bool PTank_imgProcess::twoArcsClipTheHangingArc_ROI(cv::Mat img, cv::Rect ROI, cv::Point & p1, cv::Point & p2, cv::Point2f & midP, cv::Point & p3, cv::Point & p4, std::vector<cv::Point>& allPntList, cv::Mat & canvas, bool debug)
{int endRes = 0;bool result = false;img.copyTo(canvas);p1 = cv::Point(0, 0);p2 = cv::Point(0, 0);p3 = cv::Point(0, 0);p4 = cv::Point(0, 0);midP = cv::Point2f(0, 0);allPntList.clear();cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalROI_flag = true;}result = twoArcsClipTheHangingArc(imgOriginal, p1, p2, midP, p3, p4, allPntList, canvas, debug);//调用识别算法if (debug) printf("-------------------------------------****------ roiF p1=【%d, %d】, p2=【%d, %d】\n", p1.x, p1.y, p2.x, p2.y);if (debug) printf("-------------------------------------****------ roiF p3=【%d, %d】, p4=【%d, %d】\n", p3.x, p3.y, p4.x, p4.y);if (debug) printf(" roiF midP=【%f, %f】\n", midP.x, midP.y);//img.copyTo(canvas);img.copyTo(canvas);//调试时注释掉if (result){endRes = 1;p1 += ROI_tl;p2 += ROI_tl;p3 += ROI_tl;p4 += ROI_tl;midP += cv::Point2f(ROI_tl);for (int i = 0; i < allPntList.size(); i++) {allPntList.at(i) += ROI_tl;}int w = 5;for (int i = 0; i < allPntList.size(); i++) {cv::Point curPoint = allPntList.at(i);cv::line(canvas, curPoint, cv::Point(curPoint.x - w, curPoint.y), cv::Scalar(55, 195, 40), 1);}cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);circle(canvas, midP, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, midP, 43, cv::Scalar(0, 169, 255), 1);cv::line(canvas, midP, cv::Point2f(5, midP.y), cv::Scalar(155, 195, 40), 1);cv::line(canvas, cv::Point2f(midP.x, midP.y - 5), cv::Point2f(midP.x, midP.y + 5), cv::Scalar(155, 195, 40), 1);circle(canvas, p1, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p1, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, p2, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p2, 43, cv::Scalar(255, 169, 0), 1);circle(canvas, p3, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p3, 63, cv::Scalar(0, 169, 255), 1);circle(canvas, p4, 3, cv::Scalar(0, 69, 255), 1);circle(canvas, p4, 43, cv::Scalar(255, 169, 0), 1);}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) circle(ROIcanvas, p1, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p1, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, p2, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p2, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, p3, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p3, 63, cv::Scalar(0, 169, 255), 1);if (debug) circle(ROIcanvas, p4, 3, cv::Scalar(0, 69, 255), 1);if (debug) circle(ROIcanvas, p4, 63, cv::Scalar(0, 169, 255), 1);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) printf("---------------****------ roiF p1=【%d, %d】, p2=【%d, %d】\n", p1.x, p1.y, p2.x, p2.y);if (debug) printf("---------------****------ roiF p3=【%d, %d】, p4=【%d, %d】\n", p3.x, p3.y, p4.x, p4.y);if (debug) printf("---------------****------ roiF midP=【%f, %f】\n", midP.x, midP.y);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//两弧线夹悬空的圆弧 返回五点+骨干点集 定"L"型管相贯线水平用
int mainTwoArcsClipTheHangingArc() {bool flag;//std::string filePath = "../../../../Log08141641/TestImg/src";std::string filePath = "E://vsproject//压力罐\\img\\L型管定水平";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(500, 292);cv::Point brP = cv::Point(750, 677);//cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(539, 218, 113, 513);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Point p3(90, 90);cv::Point p4(90, 90);cv::Point2f midP(90, 90);int outMidY;cv::Mat canvas;PTank_imgProcess m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}std::vector<cv::Point> allPntList;std::vector<cv::Point> tPntList;std::vector<cv::Point> bPntList;std::vector<cv::Point> mPntList;vector<string> path_name;bool getROI = true;bool lianxu = false; //循环测试if (!lianxu){string name = cv::format("\\Image_20240627151133378.png");string path = filePath + name;cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::RECURS_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(name);bool flag = m_ImageProcessing.twoArcsClipTheHangingArc_ROI(src, ROI, top, bottom, midP, p3, p4, allPntList, canvas, true);m_ImageProcessing.By4Pnt_SplitPLst_1to3(canvas, top, bottom, p3, p4, allPntList, tPntList, bPntList, mPntList, canvas, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;cout << "midP = " << midP.x << " " << midP.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::RECURS_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::RECURS_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find(".log") != std::string::npos) continue;if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) ROI = getROIFromString(i);bool flag = m_ImageProcessing.twoArcsClipTheHangingArc_ROI(src, ROI, top, bottom, midP, p3, p4, allPntList, canvas, false);m_ImageProcessing.By4Pnt_SplitPLst_1to3(canvas, top, bottom, p3, p4, allPntList, tPntList, bPntList, mPntList, canvas, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;cout << "midP = " << midP.x << " " << midP.y << endl;}canvas.copyTo(src);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::imshow("main-结果图src", src);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(10);}cout << "循环结束!!! main " << endl;}ofs.close();cv::waitKey(0);system("Pause");return 0;
}
传入原图和模板图,返回vector
/*//泡泡cv::Mat img, 原图cv::Rect ROI, cv::Mat imgTemplate:模板图片(无泡泡的图)cv::Mat &canvas,效果图可视化*/bool DetectingBubble(const cv::Mat imgOriginal, cv::Mat imgTemplate, std::vector<cv::Rect> &bubbles, cv::Mat &canvas, bool debug = false);bool DetectingBubble_ROI(cv::Mat img, cv::Mat imgTemplate, std::vector<cv::Rect> &bubbles, cv::Rect ROI, cv::Mat &canvas, bool debug = false);
bool ImageProcessing::DetectingBubble_ROI(cv::Mat img, cv::Mat imgTemplate, std::vector<cv::Rect> &bubbles, cv::Rect ROI, cv::Mat & canvas, bool debug)
{cout << __FUNCTION__ << endl;int endRes = 0;bool result = false;img.copyTo(canvas);bubbles.clear();cv::Mat imgOriginal;bool ROI_flag;//是否有给信息区cv::Point ROI_tl = cv::Point2i(ROI.x, ROI.y);cv::Point ROI_br = cv::Point2i(ROI.x + ROI.width, ROI.y + ROI.height);if (ROI_tl == cv::Point(0, 0) && ROI_br == cv::Point(0, 0) || ROI.width == 0 || ROI.height == 0){img.copyTo(imgOriginal);ROI_flag = false;}else{if (ROI_tl.x > ROI_br.x || ROI_tl.y > ROI_br.y)//信息区两点疑似传反{printf("信息区两点疑似传反!");return false;}if (ROI_tl.x < 0 || ROI_br.x > img.cols || ROI_tl.y < 0 || ROI_br.y > img.rows)//信息区的框选超出图像范围{printf("信息区的框选超出图像范围!");return false;}if (abs(ROI_tl.x - ROI_br.x) > img.cols || abs(ROI_tl.y - ROI_br.y) > img.rows)//信息区大小超出图像大小{printf("信息区大小超出图像大小!");return false;}//此时不合法的ROI都已提前返回falsecv::Rect roi(ROI_tl.x, ROI_tl.y, ROI_br.x - ROI_tl.x, ROI_br.y - ROI_tl.y);imgOriginal = img(roi); //裁剪出的ROI区域放于imgOriginalimgTemplate = imgTemplate(roi);ROI_flag = true;}result = DetectingBubble(imgOriginal, imgTemplate, bubbles, canvas, debug);//调用识别算法//if (debug) printf("-------------------------------------****------ roiF top=【%d, %d】, bottom=【%d, %d】\n", top.x, top.y, bottom.x, bottom.y);img.copyTo(canvas);//调试时注释掉cv::Mat t1;canvas.convertTo(t1, -1, 200 / 100.0, 0 + 55);//if (debug) cv::imshow("线性变换0", t1);t1.copyTo(canvas);if (result){endRes = 1;cv::putText(canvas, "true", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);//for (int i = 0; i < bubbles.size(); i++) {// //bubbles.at(i).tl.x = bubbles.at(i).tl.x + ROI_tl.x;// //bubbles.at(i).tl.y = bubbles.at(i).tl.y + ROI_tl.y;// //bubbles.at(i).br.x = bubbles.at(i).br.x + ROI_tl.x;// //bubbles.at(i).br.y = bubbles.at(i).br.y + ROI_tl.y;// cv::Rect curBR = bubbles.at(i);// bubbles.at(i).x = bubbles.at(i).x + ROI_tl.x;// bubbles.at(i).y = bubbles.at(i).y + ROI_tl.y;// //curBR.tl.x = bubbles.at(i).tl.x + ROI_tl.x;// //curBR.tl.y = bubbles.at(i).tl.y + ROI_tl.y;// //curBR.br.x = bubbles.at(i).br.x + ROI_tl.x;// //curBR.br.y = bubbles.at(i).br.y + ROI_tl.y;//}for (int i = 0; i < bubbles.size(); i++) {//可视化bubbles.at(i).x = bubbles.at(i).x + ROI_tl.x;bubbles.at(i).y = bubbles.at(i).y + ROI_tl.y;cv::Rect curBR = bubbles.at(i);cv::rectangle(canvas, curBR.tl(), curBR.br(), cv::Scalar(0, 255, 0), 1);cv::putText(canvas, to_string(i), curBR.br(), cv::FONT_HERSHEY_COMPLEX, 0.45, cv::Scalar(55, 35, 160), 1);}}else{cv::putText(canvas, "false", { cv::Point(50, 50) }, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 1);}cv::Mat ROIcanvas;img.copyTo(ROIcanvas);if (debug) rectangle(ROIcanvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);rectangle(canvas, ROI_tl, ROI_br, cv::Scalar(0, 0, 255), 1);if (debug) imshow("ROI", ROIcanvas);if (debug) imshow("ROI_canvas", canvas);//ROIcanvas.copyTo(canvas);return result;
}
调用main:
//泡泡 OneSideSquare_ROI
int main/*pp*/() {bool flag;std::string filePath = "../../../../泡泡/0708/6000";//std::string filePath = "../../../../泡泡/0708/20000";string resPath = "/output";//string resPath = filePath + "./output";cv::Point tlP = cv::Point(491, 50);cv::Point brP = cv::Point(1596, 760);tlP = cv::Point(1, 296);brP = cv::Point(1160, 2278);tlP = cv::Point(190, 0);brP = cv::Point(840, 1024);//cv::Rect ROI = cv::Rect(0, 0, 0, 0);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);//cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);//cv::Rect ROI = cv::Rect(639, 188, 125, 569);cv::Point top(90, 90);cv::Point bottom(90, 90);cv::Point2f midP(90, 90);int outMidY;cv::Mat canvas;ImageProcessing m_ImageProcessing;ofstream ofs("log.txt", ios::out);if (ofs){ofs.clear();ofs << "日志启动" << endl;}std::vector<cv::Rect> bubbles;//泡泡集合vector<Picture_set> img_buf;vector<string> path_name;//cv::Mat templ = cv::imread(filePath + cv::format("\\屏幕截图(13).png"));//模板图的灰度图cv::Mat templ = cv::imread(filePath + cv::format("\\Image_20240708175744959.png"));//6000bool getROI = !true;bool lianxu = false; //循环测试if (lianxu){std::string name = cv::format("\\Image_20240708175747311.png");string path = filePath + name;cv::Mat src = cv::imread(path);src.copyTo(canvas);cv::namedWindow("main_OriginalIMG", cv::NORMCONV_FILTER);cvSetMouseCallback("main_OriginalIMG", on_mouse_singleClick, 0);cv::imshow("main_OriginalIMG", src);cv::imshow("templ", templ);//cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) {ROI = getROIFromString(name);}//cv::Mat imgCur = src - templ;imgCur = imgOriginal - imgTemplate;//if (1) cv::imshow("减去模板图后", imgCur);bool flag = m_ImageProcessing.DetectingBubble_ROI(src, templ, bubbles, ROI, canvas, true);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cout << "\nmain ==== i " << endl;circle(canvas, top, 63, cv::Scalar(0, 69, 255), 1);circle(canvas, bottom, 63, cv::Scalar(0, 69, 255), 1);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::NORMCONV_FILTER);cvSetMouseCallback("main-结果图src", on_mouse_singleClick, 0);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::NORMCONV_FILTER);cvSetMouseCallback("main-canvas", on_mouse_singleClick, 0);cv::imshow("main-canvas", canvas);}else{vector<string> path_name;getAllFiles(filePath, path_name);cout << "path_name.size()=" << path_name.size() << endl;int number = 1;for (auto i : path_name){//cout << i.size() << endl;if (i.size() == 7) continue;if (i.find("output") != std::string::npos) continue;if (i.find(".log") != std::string::npos) continue;if (i.find(".txt") != std::string::npos) continue;if (i.find("png") == std::string::npos && i.find("bmp") == std::string::npos && i.find("jpg") == std::string::npos) continue;//if (i.find("_202404220930171") == std::string::npos) continue;std::string name = i;std::string path11 = filePath + "\\" + i;cv::Mat src = cv::imread(path11);//cv::Mat src = cv::imread(filePath + "\\" + i);cout << endl << "number【" << number << "】src path=" << i << " ;" << endl;src.copyTo(canvas);cv::imshow("main_OriginalIMG", src);//将结果图写入文件方便查看结果int len = filePath.length();//i = i.substr(i.find_last_of('\\') + 1, len);cout << "i=" << i << ", path11=" << path11 << endl;int time_start = clock();int time_end = clock();cv::Rect ROI = cv::Rect(0, 0, src.cols, src.rows);cv::Rect ROI = cv::Rect(tlP.x, tlP.y, brP.x - tlP.x, brP.y - tlP.y);if (getROI) {ROI = getROIFromString(name);}bool flag = m_ImageProcessing.DetectingBubble_ROI(src, templ, bubbles, ROI, canvas, false);time_end = clock();printf("\n耗时 %d ms \n", time_end - time_start);cout << "\nmain ==== flag " << flag << endl;if (flag) {cout << "top = " << top.x << " " << top.y << endl;cout << "bottom = " << bottom.x << " " << bottom.y << endl;}canvas.copyTo(src);//cv::putText(src, to_string(number - 1), { cv::Point(250, 250) }, cv::FONT_HERSHEY_COMPLEX, 8, cv::Scalar(255, 255, 255), 5);cv::putText(src, to_string(flag), cv::Point(src.cols / 2 - 20, src.rows / 2 - 65), cv::FONT_HERSHEY_COMPLEX, 1.75, cv::Scalar(255, 135, 160), 3);cv::namedWindow("main-结果图src", cv::NORMCONV_FILTER);cv::imshow("main-结果图src", src);cv::namedWindow("main-canvas", cv::NORMCONV_FILTER);cv::imshow("main-canvas", canvas);//将结果图写入文件方便查看结果char* filePath_ = new char[len + 1];strcpy(filePath_, filePath.c_str());len = filePath.length();char* resPath_ = new char[len + 1];strcpy(resPath_, resPath.c_str());//i.erase(0, strlen(filePath_) - strlen(resPath_) - 2);string out = filePath + resPath;cout << "\nmain ==== i " << i << endl;out.append("\\").append(i);cout << "number【" << number << "】res path=" << out << endl;cv::imwrite(out, src);number++;cout << "path_name.size() = " << path_name.size() << endl;cout << "*********************************************************************************************************************" << endl;cv::waitKey(1);}cout << "循环结束!!! main " << endl;}ofs.close();cv::waitKey(0);system("Pause");return 0;
}
***识别接口开头模板***
{bool result = false;if (imgOriginal.empty()) {printf("传入图像为空,直接返回false!!!! \n");return false;}imgOriginal.copyTo(canvas);top = cv::Point(0, 0);bottom = cv::Point(0, 0);midP = cv::Point(0, 0);cv::Mat imgGray;if (imgOriginal.type() != CV_8UC1)cv::cvtColor(imgOriginal, imgGray, cv::COLOR_BGR2GRAY);else imgOriginal.copyTo(imgGray);//if (1) {// cv::Mat imgMedianBlur;// cv::medianBlur(imgGray, imgMedianBlur, 3);// if (debug) cv::imshow("imgMedianBlur", imgMedianBlur);// imgMedianBlur.copyTo(imgGray);//}cv::Mat close;cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 5));cv::morphologyEx(imgGray, close, cv::MORPH_CLOSE, kernel);if (debug) cv::imshow("闭运算", close);cv::Mat thresholdMat;cv::adaptiveThreshold(close, thresholdMat, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 85, -15);if (debug) cv::imshow("threshold", thresholdMat);//一个不为0的像素都没有,即全黑时,直接返回falseint iVal255 = cv::countNonZero(thresholdMat);if (!iVal255) return false;std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;std::vector<std::vector<cv::Point>>::iterator k;cv::findContours(thresholdMat, contours, hierarchy, cv::RETR_EXTERNAL, CV_RETR_LIST);if (contours.size() <= 0)//图为全黑时{std::cout << "contours.size() <= 0";return false;}if (debug) printf("图像处理后 检测到的轮廓数 contours.size() = %d \n", contours.size());int remainNum = 0;//剩余的轮廓数cv::Mat tmpMat = cv::Mat(thresholdMat.rows, thresholdMat.cols, CV_8UC1, cv::Scalar(0, 0, 0));//画出轮廓;int count = 0;for (k = contours.begin(); k != contours.end(); ++k, count++) //删除小连通域的{std::vector<cv::Point> curContours = *k;if (curContours.size() < 40) continue;remainNum++;cv::drawContours(tmpMat, contours, count, cv::Scalar(255, 255, 255), -1, CV_AA, hierarchy); //用全黑色填充}if (debug) cv::imshow("tmpMat", tmpMat);if (debug) printf("删减后 剩余的轮廓数 remainNum = %d \n", remainNum);if (remainNum == 0)//图为全黑时{std::cout << "contours.size() <= 0";return false;}//------------------------------------------------------------------------------------------------------------------------------------//提取骨干点集std::vector<cv::Point> bright_point;//max点std::vector<int> bright_value;//max像素值//bright_point = extrectBackbone(tmpMat, bright_value);if (1) {if (debug) cout << "tmpMat.size() =" << tmpMat.size() << std::endl;int splitRow = tmpMat.rows / 2 - 5;cv::Mat tmpMatU, tmpMatD;tmpMat.rowRange(0, splitRow).copyTo(tmpMatU);tmpMat.rowRange(splitRow, tmpMat.rows).copyTo(tmpMatD);cv::flip(tmpMatU, tmpMatU, 0);std::vector<cv::Point> bright_pointU;//max点std::vector<cv::Point> bright_pointD;//max点std::vector<int> bright_valueU;//max像素值std::vector<int> bright_valueD;//max像素值bright_pointU = extrectBackbone(tmpMatU, bright_valueU, 0);bright_pointD = extrectBackbone(tmpMatD, bright_valueD, 0);std::reverse(bright_pointU.begin(), bright_pointU.end());for (int i = 0; i < bright_pointU.size(); i++) {//把上半部分的骨干上下翻转回cv::Point curPoint = bright_pointU.at(i);if (curPoint.x != 0) curPoint.y = tmpMatU.rows - curPoint.y - 1;//if(debug) printf("将上半截骨干排序反转:第%d 行, 【%d, %d】 ============= \n", i, curPoint.x, curPoint.y);//curPoint.x = tmpMat.cols - curPoint.x;bright_point.push_back(curPoint);}std::vector<cv::Point> bright_pointD_new;for (int i = 0; i < bright_pointD.size(); i++) {cv::Point curPoint = bright_pointD.at(i);if (curPoint.x != 0) curPoint.y = splitRow + curPoint.y;bright_pointD_new.push_back(curPoint);}bright_pointD = bright_pointD_new;bright_point.insert(bright_point.end(), bright_pointD.begin(), bright_pointD.end());std::reverse(bright_valueU.begin(), bright_valueU.end());bright_value = bright_valueU;bright_value.insert(bright_value.end(), bright_valueD.begin(), bright_valueD.end());}//有效骨干个数过少,直接返回 false !!!!int vaildBackbone = 0;//有效骨干个数for (int i = 0; i < bright_point.size(); i++){cv::Point P = bright_point.at(i);if (P != cv::Point(0, 0)) vaildBackbone++;}if (debug) printf("有效骨干个数 vaildBackbone = %d \n", vaildBackbone);if (vaildBackbone <= 30){printf("有效骨干个数过少!!!!\n");return false;}if (debug) {printf("骨干点集更新前:\n");for (int i = 0; i < bright_point.size(); i++){cv::Point curPoint = bright_point.at(i);int curGray = bright_value.at(i);//printf("骨干点集更新前:第%d 行, 【%d, %d】 灰度值:%d \n", i, curPoint.x, curPoint.y, curGray);}}std::vector<cv::Point> tmpPoint;std::vector<int> tmpValue;for (int i = 0; i < bright_point.size(); i++) {cv::Point curPoint = bright_point.at(i);if (curPoint.x == 0 || curPoint.y == 0) continue;if (tmpMat.at<uchar>(curPoint) < 185) continue;//if (imgGray.at<uchar>(curPoint) < 185) continue;tmpPoint.push_back(curPoint);}bright_point = tmpPoint;//把无效点删掉if (0) {std::vector<cv::Point> rightmost;//激光最右点集//for (int row = 0; row < tmpMat.rows; row++)//for (int row = bright_point.at(0).y; row < bright_point.at(bright_point.size() - 1).y; row++)for (int i = 0; i < bright_point.size(); i++){int row = bright_point[i].y;//for (int col = bright_point.at(row).x; col < tmpMat.cols - 1; col++)//-1是为了防崩溃for (int col = bright_point.at(i).x; col < tmpMat.cols - 1 && col < bright_point.at(i).x + 70; col++)//-1是为了防崩溃{int pv = tmpMat.at<uchar>(row, col);//int pv = tmpMat.at<uchar>(row, col);if (pv != 0 && tmpMat.at<uchar>(row, col + 1) == 0)//激光最右点入列{if (!rightmost.empty() && rightmost.back().y == row) rightmost.pop_back();rightmost.push_back(cv::Point(col - 1, row));//break;}}}bright_point = rightmost;}if (debug) {printf("骨干点集更新后:\n");for (int i = 0; i < bright_point.size(); i++) {cv::Point curPoint = bright_point.at(i);printf("骨干点集更新后:第%d 行, 【%d, %d】 \n", i, curPoint.x, curPoint.y);}}if (debug) printf("有效骨干个数 bright_point.size() = %d \n", bright_point.size());if (bright_point.size() <= 30){printf("有效骨干个数过少!!!!\n");return false;}allPntList = bright_point;//可视化骨干点集cv::Mat newArcMat = cv::Mat::zeros(tmpMat.size(), CV_8UC1);for (int i = 0; i < bright_point.size(); i++){cv::Point P = cv::Point(bright_point.at(i).x, bright_point.at(i).y);newArcMat.at<uchar>(cv::Point(bright_point.at(i).x, bright_point.at(i).y)) = 255;}cv::Mat BowCurveMat;cv::Mat imgRGB_Begin;if (newArcMat.type() != CV_8UC1)cvtColor(newArcMat, imgRGB_Begin, cv::COLOR_RGB2GRAY);else newArcMat.copyTo(imgRGB_Begin);//重叠看效果cv::addWeighted(tmpMat, 0.5, imgRGB_Begin, 0.5, 0, BowCurveMat);//if (debug) cv::namedWindow("BowCurveMat", cv::WINDOW_NORMAL);if (debug) cv::imshow("BowCurveMat", BowCurveMat);result = true;// TODOreturn result;
}
相关文章:

ROI 接口便捷修改
传入的图片截取ROI后再进入识别接口 (识别接口比ROI接口的函数参数少一个传入的ROI) 无点只有点集 返回双点集 //平直冷侧翅片 bool ImageProcessingTest::straightColdSideFin_ROI(cv::Mat img, cv::Rect ROI, std::vector<cv::Point>& topL…...

jenkins打包java项目报错Error: Unable to access jarfile tlm-admin.jar
jenkins打包boot项目 自动重启脚本失败 查看了一下项目日志报错: Error: Unable to access jarfile tlm-admin.jar我检查了一下这个配置,感觉没有问题,包可以正常打, cd 到项目目录下面,手动执行这个sh脚本也是能正常…...

SQL Server设置端口:跨平台指南
在使用SQL Server时,设置或修改其监听的端口是确保数据库服务安全访问和高效管理的重要步骤。由于SQL Server可以部署在多种操作系统上,包括Windows、Linux和Docker容器等,因此设置端口的步骤和方法也会因平台而异。本文将为您提供一个跨平台…...

ActiveMQ-CVE-2023-46604
Apache ActiveMQ OpenWire 协议反序列化命令执行漏洞 OpenWire协议在ActiveMQ中被用于多语言客户端与服务端通信。在Apache ActvieMQ5.18.2版本以及以前,OpenWire协议通信过程中存在一处反序列化漏洞,该漏洞可以允许具有网络访问权限的远程攻击者通过操作…...

TensorBoard ,PIL 和 OpenCV 在深度学习中的应用
重要工具介绍 TensorBoard: 是一个TensorFlow提供的强大工具,用于可视化和理解深度学习模型的训练过程和结果。下面我将介绍TensorBoard的相关知识和使用方法。 TensorBoard 简介 TensorBoard是TensorFlow提供的一个可视化工具,用于&#x…...

【超音速 专利 CN117576413A】基于全连接网络分类模型的AI涂布抓边处理方法及系统
申请号CN202311568976.4公开号(公开)CN117576413A申请日2023.11.22申请人(公开)超音速人工智能科技股份有限公司发明人(公开)张俊峰(总); 杨培文(总); 沈俊羽…...

iPhone数据恢复篇:iPhone 数据恢复软件有哪些
问题:iPhone 15 最好的免费恢复软件是什么?我一直在寻找一个恢复程序来恢复从iPhone中意外删除的照片,联系人和消息,但是我有很多选择。 谷歌一下,你会发现许多付费或免费的iPhone数据恢复工具,声称它们可…...

Html5+Css3学习笔记
Html5 CSS3 一、概念 1.什么是html5 html: Hyper Text Markup Language ( 超文本标记语言) 文本:记事本 超文本: 文字、图片、音频、视频、动画等等(网页) html语言经过浏览器的编译显示成超文本 开发者使用5种浏览器…...

WPF学习(2) -- 样式基础
一、代码 <Window x:Class"学习.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expression/blend/2008&…...

独家揭秘!五大内网穿透神器,访问你的私有服务
本文精心筛选了五款炙手可热的内网穿透工具,它们各怀绝技,无论您是企业用户、独立开发者,还是技术探索者,这篇文章都物有所值,废话不多说,主角们即将上场。 目录 1. 巴比达 - 安全至上的企业护航者 2. 花…...

Ubuntu 编译和运行ZLMediaKit
摘要 本文描述了如何在Ubuntu上构建ZLMediaKIt项目源码,以及如何体验其WebRTC推流和播放功能。 实验环境 操作系统版本:Ubuntu 22.04.3 LTS gcc版本:11.4.0 g版本:11.4.0 依赖库安装 #让ZLMediaKit媒体服务器具备WebRTC流转发…...

基于JavaSpringBoot+Vue+uniapp微信小程序校园宿舍管理系统设计与实现
基于JavaSpringBootVueuniapp微信小程序实现校园宿舍管理系统设计与实现 目录 第一章 绪论 1.1 研究背景 1.2 研究现状 1.3 研究内容 第二章 相关技术介绍 2.1 Java语言 2.2 HTML网页技术 2.3 MySQL数据库 2.4 Springboot 框架介绍 2.5 VueJS介绍 2.6 ElementUI介绍…...

Hive的基本操作(创建与修改)
必备知识 数据类型 基本类型 类型写法字符char, varchar, string✔整数tinyint, smallint, int✔, bigint✔小数float, double, numeric(m,n), decimal(m,n)✔布尔值boolean✔时间date✔, timestamp✔ 复杂类型(集合类型) 1、数组:array<T> 面向用户提供…...

Linux开发讲课37--- ARM的22个常用概念
1. ARM中一些常见英文缩写解释 MSB:最高有效位; LSB:最低有效位; AHB:先进的高性能总线; VPB:连接片内外设功能的VLSI外设总线; EMC:外部存储器…...

7-1、2、3 IPFS介绍使用及浏览器交互(react+区块链实战)
7-1、2、3 IPFS介绍使用及浏览器交互(react区块链实战) 7-1 ipfs介绍7-2 IPFS-desktop使用7-3 reactipfs-api浏览器和ipfs交互 7-1 ipfs介绍 IPFS区块链上的文件系统 https://ipfs.io/ 这个网站本身是需要科学上网的 Ipfs是点对点的分布式系统 无限…...

CentOS 7 中出现 cannot open Packages database in /var/lib/rpm 错误
转载自:https://www.jianshu.com/p/423306f43e72 # 进入 rpmdb 所在目录 [roothostbase ~]# cd /var/lib/rpm [roothostbase rpm]# ls Basenames __db.001 __db.003 Group Name Packages Requirename Sigmd5 Conflictname __db.002 Dirnames Ins…...

【java深入学习第6章】深入解析Spring事件监听机制
在Spring框架中,事件监听机制是一个强大且灵活的功能,允许我们在应用程序中发布和监听事件。这种机制可以帮助我们实现松耦合的设计,使得不同模块之间的通信更加灵活和可维护。本文将详细介绍Spring的事件监听机制,并通过代码示例…...

Flask与Celery实现Python调度服务
文章目录 Flask与Celery实现Python调度服务一、前言1.组件2.场景说明3.环境 二、安装依赖1.安装Anaconda3.安装redis2.安装依赖包 三、具体实现1.目录结构2.业务流程3.配置文件4.Celery程序5.Flask程序6.测试脚本7.程序启动1)Windows开发调试2)Linux服务…...

Eureka应用场景和优势
Eureka是一款由Netflix开源的服务注册与发现框架,在微服务架构中扮演着至关重要的角色。以下是Eureka的应用场景和优势: Eureka的应用场景 Eureka主要应用于微服务架构中,特别是在大型、复杂的分布式系统中,用于管理和发现服务。…...

prompt第三讲-PromptTemplate
文章目录 前提回顾PromptTemplateprompt 模板定义以f-string渲染格式以mustache渲染格式以jinja2渲染格式直接实例化PromptTemplatePromptTemplate核心变量 prompt value生成invokeformat_prompt(不建议使用)format(不建议使用) batchstreamainvoke PromptTemplate核心方法part…...

卷积神经网络图像识别车辆类型
卷积神经网络图像识别车辆类型 1、图像 自行车: 汽车: 摩托车: 2、数据集目录 3、流程 1、获取数据,把图像转成矩阵,并随机划分训练集、测试集 2、把标签转为数值,将标签向量转换为二值矩阵 3、图像数据归一化,0-1之间的值 4、构造卷积神经网络 5、设置图像输入…...

【接口设计】用 Swagger 实现接口文档
用 Swagger 实现接口文档 1.配置 Swagger1.1 添加 Swagger 依赖1.2 创建 Swagger 配置类 2.编写接口文档 在项目开发中,一般都是由前后端工程师共同定义接口,编写接口文档,之后大家根据这个接口文档进行开发、维护。为了便于编写和维护稳定&a…...

TensorFlow系列:第四讲:MobileNetV2实战
一. 加载数据集 编写工具类,实现数据集的加载 import keras""" 加载数据集工具类 """class DatasetLoader:def __init__(self, path_url, image_size(224, 224), batch_size32, class_modecategorical):self.path_url path_urlself…...

Redis+Caffeine 实现两级缓存实战
RedisCaffeine 实现两级缓存 背景 事情的开始是这样的,前段时间接了个需求,给公司的商城官网提供一个查询预计送达时间的接口。接口很简单,根据请求传的城市仓库发货时间查询快递的预计送达时间。因为商城下单就会调用这个接口ÿ…...

SpringBoot:SpringBoot中如何实现对Http接口进行监控
一、前言 Spring Boot Actuator是Spring Boot提供的一个模块,用于监控和管理Spring Boot应用程序的运行时信息。它提供了一组监控端点(endpoints),用于获取应用程序的健康状态、性能指标、配置信息等,并支持通过 HTTP …...

STM32-I2C硬件外设
本博文建议与我上一篇I2C 通信协议共同理解 合成一套关于I2C软硬件体系 STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担 特点: 多主机功能&#x…...

暑假第一次作业
第一步:给R1,R2,R3,R4配IP [R1-GigabitEthernet0/0/0]ip address 192.168.1.1 24 [R1-Serial4/0/0]ip address 15.0.0.1 24 [R2-GigabitEthernet0/0/0]ip address 192.168.2.1 24 [R2-Serial4/0/0]ip address 25.0.0.1 24 [R3-GigabitEthernet0/0/0]ip address 192.…...

【算法专题】快速排序
1. 颜色分类 75. 颜色分类 - 力扣(LeetCode) 依据题意,我们需要把只包含0、1、2的数组划分为三个部分,事实上,在我们前面学习过的【算法专题】双指针算法-CSDN博客中,有一道题叫做移动零,题目要…...

debian 12 PXE Server 批量部署系统
pxe server 前言 PXE(Preboot eXecution Environment,预启动执行环境)是一种网络启动协议,允许计算机通过网络启动而不是使用本地硬盘。PXE服务器是实现这一功能的服务器,它提供了启动镜像和引导加载程序,…...

【Pytorch】RNN for Image Classification
文章目录 1 RNN 的定义2 RNN 输入 input, h_03 RNN 输出 output, h_n4 多层5 小试牛刀 学习参考来自 pytorch中nn.RNN()总结RNN for Image Classification(RNN图片分类–MNIST数据集)pytorch使用-nn.RNNBuilding RNNs is Fun with PyTorch and Google Colab 1 RNN 的定义 nn.…...