此图为2值图,请教把液晶区域裁剪出来的代码,谢谢。 后续打算学习把符号小数点和数字裁剪出来,谢谢。
4条回答 默认 最新
关注 获得2.30元问题酬金 颜色翻转以下,然后进行中值滤波,最后求连通域,得到最大的连通域(现有图片中的最大黑色区域)。
对最大连通域进行闭运算,将连通域中的数字变成白色。
用连通域做mask,得到目标图。#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> using namespace std; using namespace cv; //修改自以下链接,博主添加了pad,使两列图像边多了空格 //https ://blog.csdn.net/Beking17113/article/details/122304671 void multipleImage(vector<Mat> imgVector, Mat& dst, int imgCols, int MAX_PIXEL = 600) { //两列图像间的空白区域 int pad = 10; int imgNum = imgVector.size(); //选择图片最大的一边 将最大的边按比例变为300像素 Size imgOriSize = imgVector[0].size(); int imgMaxPixel = max(imgOriSize.height, imgOriSize.width); //获取最大像素变为MAX_PIXEL的比例因子 double prop = imgMaxPixel < MAX_PIXEL ? (double)imgMaxPixel / MAX_PIXEL : MAX_PIXEL / (double)imgMaxPixel; Size imgStdSize(imgOriSize.width * prop, imgOriSize.height * prop); //窗口显示的标准图像的Size Mat imgStd; //标准图片 Point2i location(0, 0); //坐标点(从0,0开始) //Mat imgWindow(imgStdSize.height * ((imgNum - 1) / imgCols + 1), imgStdSize.width * imgCols+ pad * imgCols-pad, imgVector[0].type()); int imgRows = (imgNum - 1) / imgCols + 1; Mat imgWindow = Mat::zeros(imgStdSize.height * imgRows + pad * imgRows - pad, imgStdSize.width * imgCols + pad * imgCols - pad, imgVector[0].type()); for (int i = 0; i < imgNum; i++) { location.x = (i % imgCols) * (imgStdSize.width + pad); location.y = (i / imgCols) * imgStdSize.height; resize(imgVector[i], imgStd, imgStdSize, prop, prop, INTER_LINEAR); //设置为标准大小 //将imgStd复制到imgWindow的指定区域中 imgStd.copyTo(imgWindow(Rect(location, imgStdSize))); } dst = imgWindow; } void imshows( string title, vector<Mat> imgVector, int imgCols = -1) { Mat dst; if (imgCols == -1) { imgCols = imgVector.size(); } multipleImage(imgVector, dst, imgCols); namedWindow(title); imshow(title, dst); imwrite(title + ".png", dst); } Mat readImg(string path) { Mat img = imread(path, 0);//左侧:图片路径 resize(img, img, { 512,512 }); int thres_ = 128; cv::threshold(img, img, thres_, 255, THRESH_BINARY);//大于阈值返回 最大值 255 小于返回0 cv::medianBlur(img, img, 3); return img; } Mat findLargesrArea(Mat srcImage) { Mat temp; Mat labels; srcImage.copyTo(temp); //1. 标记连通域 int n_comps = connectedComponents(temp, labels, 4, CV_16U); vector<int> histogram_of_labels; for (int i = 0; i < n_comps; i++)//初始化labels的个数为0 { histogram_of_labels.push_back(0); } int rows = labels.rows; int cols = labels.cols; for (int row = 0; row < rows; row++) //计算每个labels的个数 { for (int col = 0; col < cols; col++) { histogram_of_labels.at(labels.at<unsigned short>(row, col)) += 1; } } histogram_of_labels.at(0) = 0; //将背景的labels个数设置为0 //2. 计算最大的连通域labels索引 int maximum = 0; int max_idx = 0; for (int i = 0; i < n_comps; i++) { if (histogram_of_labels.at(i) > maximum) { maximum = histogram_of_labels.at(i); max_idx = i; } } //3. 将最大连通域标记为1 for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { if (labels.at<unsigned short>(row, col) == max_idx) { labels.at<unsigned short>(row, col) = 255; } else { labels.at<unsigned short>(row, col) = 0; } } } //4. 将图像更改为CV_8U格式 labels.convertTo(labels, CV_8U); return labels; } int main(int argc, char* argv[]) { string p1 = "D:\\test.png"; Mat im1 = readImg(p1); Mat inv = 255 - im1; Mat element = getStructuringElement(MORPH_RECT, Size(9, 9)); morphologyEx(inv, inv, MORPH_OPEN, element);//消除毛刺,删除部分连通域 //获取最大的连通域 Mat maxareo = findLargesrArea(inv); //闭合连通域中的数字 Mat element2 = getStructuringElement(MORPH_RECT, Size(71, 71)); Mat maxareo_close, maxareo_close_erode,result; morphologyEx(maxareo, maxareo_close, MORPH_CLOSE, element2);//消除毛刺,删除部分连通域 Mat element3 = getStructuringElement(MORPH_RECT, Size(31, 31)); morphologyEx(maxareo_close, maxareo_close_erode, MORPH_ERODE, element3);//因为图像边缘也被连接了,这里做删除 result = maxareo_close_erode.mul(im1); imshows("二值图", {im1,inv ,maxareo_close_erode,result },2); //imshow( inv); waitKey(); }
按照前面的代码,再优化以下流程,得到以下结果
int main(int argc, char* argv[]) { string p1 = "D:\\test.png"; Mat im1 = readImg(p1); Mat inv = 255 - im1; Mat element = getStructuringElement(MORPH_RECT, Size(9, 9)); morphologyEx(inv, inv, MORPH_OPEN, element);//消除毛刺,删除部分连通域 //获取最大的连通域 Mat maxareo = findLargesrArea(inv); //闭合连通域中的数字 Mat element2 = getStructuringElement(MORPH_RECT, Size(71, 71)); Mat maxareo_close, maxareo_close_big_erode,result; morphologyEx(maxareo, maxareo_close, MORPH_CLOSE, element2);//消除毛刺,删除部分连通域 Mat maxareo_close_big = Mat::zeros({ im1.rows+40,im1.cols+40}, im1.type()); maxareo_close.copyTo(maxareo_close_big(Rect({20,20}, im1.size()))); Mat element3 = getStructuringElement(MORPH_RECT, Size(39, 39)); morphologyEx(maxareo_close_big, maxareo_close_big_erode, MORPH_ERODE, element3);//因为图像边缘也被连接了,这里做删除 Mat maxareo_close_erode = maxareo_close_big_erode(Rect({ 20,20 }, im1.size())); result = maxareo_close_erode.mul(im1); imshows("二值图", {im1,inv ,maxareo_close_erode,result },2); //imshow( inv); waitKey(); }
解决 无用评论 打赏 举报 编辑记录
悬赏问题
- ¥100 求汇川机器人IRCB300控制器和示教器同版本升级固件
- ¥15 用visualstudio2022创建vue项目后无法启动
- ¥15 x趋于0时tanx-sinx极限可以拆开算吗
- ¥500 把面具戴到人脸上,请大家贡献智慧
- ¥15 任意一个散点图自己下载其js脚本文件并做成独立的案例页面,不要作在线的,要离线状态。
- ¥15 各位 帮我看看如何写代码,打出来的图形要和如下图呈现的一样,急
- ¥30 c#打开word开启修订并实时显示批注
- ¥15 如何解决ldsc的这条报错/index error
- ¥15 VS2022+WDK驱动开发环境
- ¥30 关于#java#的问题,请各位专家解答!