最近我做了我的第一个视觉应用程序。 我的代码可以识别某种颜色的大理石,并为我提供该大理石的X,Y,Z坐标。 为了调试和设置系统,我编写了一些代码,可以轻松地对其进行调整和尝试设置。 这段代码尝试检测图像中的所有大理石,并通过用绿色点标记来告诉我大理石在哪里。
基本上我的代码是这样的: 我的相机拍照。
它会寻找一定范围内的颜色,并以此遮罩(范围内为白色,范围内为黑色),例如:。
然后我使用houghcircles
命令在此图像中寻找圆圈。
我从每个检测到的圆中提取中心点,并将其放在原始图像上,如下所示:(绿色点=中心圆)
我的检测仍然存在一些问题,但目前我很满意。
现在,我想知道的是:是否可以在每个标记的中心点旁边放一个百分比,告诉我程序如何确定它是一个圆。
如果您有任何其他建议或问题,请随时提出。 我将代码放在下面:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <librealsense2/rs.hpp>
using namespace std;
using namespace cv;
Mat image;
Mat imgHSV;
Mat OutputImage;
Mat testframe;
int iLowH = 104;
int iHighH = 111;
int iLowS = 109;
int iHighS = 155;
int iLowV = 120;
int iHighV = 255;
int acc = 1;
int rows = 10;
int para1 = 100;
int para2 = 7;
int minRad = 3;
int maxRad = 14;
static void HSVthreshold(int, int, int, int, int, int, void*)
{
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), OutputImage);
}
static void Circle_detector(int, int, int, int, int, void*)
{
vector<Vec3f> circles;
HoughCircles(OutputImage, circles, HOUGH_GRADIENT, 1,
OutputImage.rows / rows, //change to detect circles that are closer to eachother
para1, para2, minRad, maxRad); //chang last to parameters to detect larger or smaller circles
for (size_t i = 0; i < circles.size(); i++)
{
Vec3i c = circles[i];
Point center = Point(c[0], c[1]);
// circle center
circle(testframe, center, 1, Scalar(0, 255, 0), 2, LINE_AA);
// circle outline
int radius = c[2];
circle(imgHSV, center, radius, Scalar(255, 0, 0), 2, LINE_AA);
}
}
int main()
{
// Contructing piplines and other stuff to receive data from the realsense camera.
//Contruct a pipeline which abstracts the device
rs2::pipeline pipe;
//Create a configuration for configuring the pipeline with a non default profile
rs2::config cfg;
//Add desired streams to configuration
cfg.enable_stream(RS2_STREAM_COLOR, 640, 480, RS2_FORMAT_BGR8, 30);
//Instruct pipeline to start streaming with the requested configuration
pipe.start(cfg);
// Camera warmup - dropping several first frames to let auto-exposure stabilize
rs2::frameset frames;
for (int i = 0; i < 30; i++)
{
//Wait for all configured streams to produce a frame
frames = pipe.wait_for_frames();
}
while (waitKey(1) < 0)
{
frames = pipe.wait_for_frames();
//Get each frame
rs2::frame color_frame = frames.get_color_frame();
// Creating OpenCV Matrix from a color image
Mat color(Size(640, 480), CV_8UC3, (void*)color_frame.get_data(), Mat::AUTO_STEP);
// Display in a GUI
if (color.empty())
{
cerr << "image was not generated !" << endl;
return 1;
}
testframe = color;
namedWindow("Display Image", WINDOW_AUTOSIZE);
imshow("Display Image", color);
//convert RGB to HSV
cvtColor(color, imgHSV, COLOR_BGR2HSV);
//Create windows
namedWindow("image", WINDOW_AUTOSIZE); //window for original image
namedWindow("Control", WINDOW_AUTOSIZE); //window for HSV-control sliders
namedWindow("Output", WINDOW_AUTOSIZE); //window for output mask
namedWindow("Control HoughCircles", WINDOW_AUTOSIZE); //window for HoughCircle sliders
namedWindow("Test-window", WINDOW_AUTOSIZE);
//Create trackbars in "Control HSV" window
createTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
createTrackbar("HighH", "Control", &iHighH, 179);
createTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
createTrackbar("HighS", "Control", &iHighS, 255);
createTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
createTrackbar("HighV", "Control", &iHighV, 255);
int key = 0;
while (key != 27) { // 27 is escape
HSVthreshold(iLowH, iHighH, iLowS, iHighS, iLowV, iHighV, 0);
imshow("Output", OutputImage);
imshow("image", imgHSV);
key = waitKey(1); // wait at most 1 ms for input, if nothing was pressed result is -1
}
//Optional filter --> does not work properly at the moment <--
//morphological opening (remove small objects from the foreground)
erode(OutputImage, OutputImage, getStructuringElement(MORPH_ELLIPSE, Size(1, 1)));
dilate(OutputImage, OutputImage, getStructuringElement(MORPH_ELLIPSE, Size(1, 1)));
//morphological closing (fill small holes in the foreground)
dilate(OutputImage, OutputImage, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
erode(OutputImage, OutputImage, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
imshow("Output", OutputImage);
waitKey();
//Create trackbars in "Control HoughCircles" window
createTrackbar("Distance between detections", "Control HoughCircles", &rows, 50); //detection distance (0 - 50)
createTrackbar("Upper threshold for internal canny edge", "Control HoughCircles", ¶1, 100); //upper threshold for internal canny edge detector (0 - 100)
createTrackbar("threshold for internal canny edge", "Control HoughCircles", ¶2, 50); //threshold for internal canny edge detector (0 - 50)
createTrackbar("Min radius", "Control HoughCircles", &minRad, 200); //minimum circle radius (0 - 200)
createTrackbar("Max radiu", "Control HoughCircles", &maxRad, 200); // maximum circle radius (0 - 200)
int key2 = 0;
while (key2 != 27) { // 27 is escape
Circle_detector(rows, para1, para2, minRad, maxRad, 0);
imshow("image", imgHSV);
imshow("Test-window", testframe);
key2 = waitKey(1); // wait at most 1 ms for input, if nothing was pressed result is -1
}
waitKey();
}
return 0;
}
编辑: 我为测试材料添加了一些新图片,可悲的是,由于光线条件,这并不完全等同于上述情况。
答案 0 :(得分:1)
我尝试了您添加的图片。与您的代码相比,我没有使用其他不同的东西。我专注于检查每个圆圈内的像素。这是我的步骤:
medianBlur
降低噪音HoughCircles
应用于二进制图像HoughCircles
的输出,每个圆都被矩形裁剪这是我的代码和结果(结果与您的没什么不同,重要的部分是检查圆圈内):
代码:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <librealsense2/rs.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat color = imread("/ur/image/directory/marble.png",1);
Mat hsv;
cvtColor(color, hsv, COLOR_BGR2HSV);
Mat board = Mat::zeros(hsv.rows,hsv.cols,CV_8UC1);
for(int i=0; i<hsv.rows; i++)
{
for(int j=0; j<hsv.cols; j++)
{
if(hsv.at<Vec3b>(Point(j,i))[2]<60 && hsv.at<Vec3b>(Point(j,i))[2]>20 && hsv.at<Vec3b>(Point(j,i))[1]<120 && hsv.at<Vec3b>(Point(j,i))[1]>50
&& hsv.at<Vec3b>(Point(j,i))[0]<105 && hsv.at<Vec3b>(Point(j,i))[0]>85)
board.at<uchar>(Point(j,i)) = 254;
}
}
medianBlur(board,board,3);
vector<Vec3f> circles;
HoughCircles(board, circles, HOUGH_GRADIENT, 1,
board.rows / 10, //change to detect circles that are closer to eachother
100, 7, 3, 14); //chang last to parameters to detect larger or smaller circles
for (size_t i = 0; i < circles.size(); i++)
{
Vec3i cc = circles[i];
Point center = Point(cc[0], cc[1]);
// circle center
circle(color, center, 1, Scalar(0, 255, 0), 2, LINE_AA);
// circle outline
int radius = cc[2];
circle(color, center, radius, Scalar(255, 0, 0), 2, LINE_AA);
// Firstly, Crop that region
Rect crop(center.x-radius-5, center.y-radius-5,2*radius+10,2*radius+10);
Mat crop_for_test = hsv(crop);
//Secondly, check each pixel inside the circle or not
for(int r=0; r<crop_for_test.rows; r++)
{
for(int c=0; c<crop_for_test.cols; c++)
{
double length_to_center = norm(Point(cc[0]-(center.x-radius-5), cc[1]-(center.y-radius-5))-Point(r,c));
if(length_to_center<radius)
{
// Here all points inside the circle
cout<<"H value: "<<to_string(crop_for_test.at<Vec3b>(Point(r,c))[2])<<" "<<"S value: "
<<to_string(crop_for_test.at<Vec3b>(Point(r,c))[1])<<" "<<"V value: "
<<to_string(crop_for_test.at<Vec3b>(Point(r,c))[0])<<endl;
}
}
}
}
imshow("board",board);
imshow("hsv",hsv);
imshow("rgb",color);
waitKey(0);
return 0;
}
HSV输入:
过滤后的二进制文件:
输出: