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…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
