要求描述:
- 通过亮度和颜色的设定标示出引脚根部(本体) 部分
- 通过亮度和颜色的设定标示出引脚部分
- 通过亮度和颜色的设定标示出焊锡部分
原图为:
选取的ROI区域:
灰度图:
通过亮度和颜色的设定标示出引脚根部(本体) 部分
通过亮度和颜色的设定标示出引脚部分
通过亮度和颜色的设定标示出焊锡部分(引脚的头和尾)
思想是;把要处理的roi区域复制为两个图像,一个用来处理打掩模,以及满足一定的条件做一些操作,然后在把他加到原有没有处理的ROI图像上。
代码:
主函数test.cpp为:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<fstream>
#include<quickopencv.h>
using namespace cv;
using namespace std;
Mat roi_select(Mat& image, Point sp, Point ep) {
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
Rect box(sp.x, sp.y, dx, dy);//ROI区域大小
Mat new_img = image(box);
/*QuickDemo qd;
Mat ROI_his = qd.histogram_grayImage(new_img);
namedWindow("ROI_his", WINDOW_FREERATIO);
imshow("ROI_his", ROI_his);*/
return new_img;
}
int main() {
Mat src = imread("C:\\Users\\Administrator\\Documents\\WXWork\\1688850162194623\\Cache\\File\\2021-08\\0015.bmp");
if (src.empty())
{
printf("could not load image...");
return -1;
}
//namedWindow("input_image", WINDOW_FREERATIO);
//imshow("input_image", src);
Mat roi_src = roi_select(src, Point(672, 1571), Point(2007, 1724));
namedWindow("roi_src", WINDOW_AUTOSIZE);
imshow("roi_src", roi_src);
Mat gray_roi_src;
cvtColor(roi_src, gray_roi_src, COLOR_BGR2GRAY);
imshow("gray_roi_src", gray_roi_src);
QuickDemo qd;
//引脚根部搜索:通过亮度和颜色的设定标示出引脚本体部分
Mat mask_img = qd.lead_mask(roi_src, gray_roi_src);
//通过亮度和颜色的设定标示出引脚部分
Mat after_mask = qd.sub_lead_mask(mask_img, gray_roi_src);
imshow("after_mask", after_mask);
//通过亮度和颜色的设定标焊锡部分(引脚的头和尾)
Mat box_label = qd.min_box(roi_src, after_mask);
imshow("box_label", box_label);
waitKey(0);
return 0;
}
源函数为:
// 打掩模
Mat QuickDemo::lead_mask(Mat& image,Mat &gray_image)
{
int height = image.rows;
int width = image.cols;
Mat dstImg = image.clone();// 新图像(寄存图像,输出就是这张图像)
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (image.at<Vec3b>(i, j)[0] < 150
&& image.at<Vec3b>(i, j)[1] < 133
&& image.at<Vec3b>(i, j)[2] < 150)
{
dstImg.at<Vec3b>(i, j)[0] = 245;
dstImg.at<Vec3b>(i, j)[1] = 4;
dstImg.at<Vec3b>(i, j)[2] = 251;
}
}
}
namedWindow("lead_mask", WINDOW_AUTOSIZE);
imshow("lead_mask", dstImg);
return dstImg;
}
Mat QuickDemo::sub_lead_mask(Mat& image, Mat& gray_image)
{
int height = gray_image.rows;
int width = gray_image.cols;
int threshold_value = 100;
int threshold_max = 255;
vector<Point> points;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
if (image.at<Vec3b>(row, col)[0] > 20
&& image.at<Vec3b>(row, col)[1] > 20
&& image.at<Vec3b>(row, col)[2] > 20
&& gray_image.at<uchar>(row, col) > 20)
{
image.at<Vec3b>(row, col)[0] = 0;
image.at<Vec3b>(row, col)[1] = 0;
image.at<Vec3b>(row, col)[2] = 0;
}
}
}
//imshow("output", image);
return image;
}
Mat QuickDemo::min_box(Mat& rgb_image, Mat& after_mask)
{
Mat src_g;
cvtColor(rgb_image, src_g, COLOR_BGR2GRAY);
Mat dstImg = after_mask.clone();
Mat binary_src;
threshold(src_g, binary_src, 80, 255, THRESH_BINARY);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(binary_src, contours, hierarchy,
RETR_EXTERNAL, CHAIN_APPROX_NONE);
vector<Rect> boundRect(contours.size()); //定义外接矩形集合
Point2f rect[4];
for (int i = 0; i < contours.size(); i++)
{
boundRect[i] = boundingRect(Mat(contours[i]));
rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8);
}
return dstImg;
}