机器视觉检测物体要根据检测对象的特征找到最方便快捷的方法,最近做了一个靠颜色像素来区分电线的小项目,颜色区分是inRange方法,这个方法检测的是HSV彩色图像的范围,需要将图像转换为HSV图像。
如图,要检测图中六条线是否都接好并且位置没有错误,观察背景,大多都是灰黑色的物体,只有这些电线颜色比较鲜明,因此选择用颜色像素来区分。
设计算法:其实也没有什么算法,每个线的颜色范围,就是用制图工具来采集一下各个颜色的BGR像素范围,因为每条线的亮度并不完全一样,只要获取看起来最亮的一点和看起来最暗的一点,就能获取到每天直线的颜色像素范围,但是要检测的不仅仅是存不存在,还要检测各个线的位置是否正确,由于这张图较大,所以应该先获取到电线的大概位置,那么就要利用图中其他明显的特征,如图,下面的接头是红色的,这片红色在图中占的比例较大,而且比较方面寻找,所以可以先找一下这个红色的接头
找到之后,就能获取红色接头的位置,因为相机与接线的位置都是固定的,所以每次拍的照片都不会差太多,那么只要能找到这个红色接头,为它做一个外包矩形,根据矩形的中点,向右移动部分像素,这个要根据实际情况决定,然后大概得到一个范围,把六条线的位置可以剪切出来。
如图,切出这样一张图之后,就可以根据颜色来区分每条线是否接好以及位置是否正确。因为我们获取的像素范围是BGR的,所以需要自己计算成HSV的。
def rgb2hsv(r, g, b):
r, g, b = r/255.0, g/255.0, b/255.0
mx = max(r, g, b)
mn = min(r, g, b)
m = mx-mn
if mx == mn:
h = 0
elif mx == r:
if g >= b:
h = ((g-b)/m)*60
else:
h = ((g-b)/m)*60 + 360
elif mx == g:
h = ((b-r)/m)*60 + 120
elif mx == b:
h = ((r-g)/m)*60 + 240
if mx == 0:
s = 0
else:
s = m/mx
v = mx
H = h / 2
S = s * 255.0
V = v * 255.0
return H, S, V
得到了像素范围之后,就要去检测各个线的位置,以红色为例:
def redFind(image):
lower = np.array([168, 43, 46])
upper = np.array([180, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
openI = cv2.morphologyEx(mask,cv2.MORPH_OPEN,s,iterations=1)
closeI = cv2.morphologyEx(openI,cv2.MORPH_CLOSE,s,iterations=1)
contours, hierarchy = cv2.findContours(closeI, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
print("红色:", int((rect[0][1] + rect[1][1]/2)))
cv2.imshow("aaa", closeI)
cv2.waitKey(1000)
如图得到了红色电线的二值图像,通过最小外接矩形可以得到它的大概位置,如下图这是各个直线中点的纵向坐标。
附上代码:
Python代码:
import cv2
import numpy as np
def redFind(image):
lower = np.array([168, 43, 46])
upper = np.array([180, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
openI = cv2.morphologyEx(mask,cv2.MORPH_OPEN,s,iterations=1)
closeI = cv2.morphologyEx(openI,cv2.MORPH_CLOSE,s,iterations=1)
contours, hierarchy = cv2.findContours(closeI, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
print("红色:", int((rect[0][1] + rect[1][1]/2)))
cv2.imshow("aaa", closeI)
cv2.waitKey(1000)
def purpleFind(image):
lower = np.array([142, 43, 46])
upper = np.array([147, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
openI = cv2.morphologyEx(mask,cv2.MORPH_OPEN,s,iterations=1)
closeI = cv2.morphologyEx(openI,cv2.MORPH_CLOSE,s,iterations=1)
contours, hierarchy = cv2.findContours(closeI, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
print("紫色:", int((rect[0][1] + rect[1][1]/2)))
cv2.imshow("aaa", closeI)
cv2.waitKey(1000)
def blueFind(image):
lower = np.array([102, 43, 46])
upper = np.array([112, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
openI = cv2.morphologyEx(mask,cv2.MORPH_OPEN,s,iterations=1)
closeI = cv2.morphologyEx(openI,cv2.MORPH_CLOSE,s,iterations=1)
contours, hierarchy = cv2.findContours(closeI, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
print("蓝色:", int((rect[0][1] + rect[1][1]/2)))
cv2.imshow("aaa", closeI)
cv2.waitKey(1000)
def yellowFind(image):
lower = np.array([20, 43, 46])
upper = np.array([25, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
openI = cv2.morphologyEx(mask,cv2.MORPH_OPEN,s,iterations=1)
closeI = cv2.morphologyEx(openI,cv2.MORPH_CLOSE,s,iterations=1)
contours, hierarchy = cv2.findContours(closeI, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
print("黄色:", int((rect[0][1] + rect[1][1]/2)))
cv2.imshow("aaa", closeI)
cv2.waitKey(1000)
def orangeFind(image):
lower = np.array([11, 43, 46])
upper = np.array([15, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
openI = cv2.morphologyEx(mask,cv2.MORPH_OPEN,s,iterations=1)
closeI = cv2.morphologyEx(openI,cv2.MORPH_CLOSE,s,iterations=1)
contours, hierarchy = cv2.findContours(closeI, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
print("橙色:", int((rect[0][1] + rect[1][1]/2)))
cv2.imshow("aaa", closeI)
cv2.waitKey(1000)
def brownFind(image):
lower = np.array([3, 43, 46])
upper = np.array([8, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
openI = cv2.morphologyEx(mask,cv2.MORPH_OPEN,s,iterations=1)
closeI = cv2.morphologyEx(openI,cv2.MORPH_CLOSE,s,iterations=1)
contours, hierarchy = cv2.findContours(closeI, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
print("棕色:", int((rect[0][1] + rect[1][1]/2)))
cv2.imshow("aaa", closeI)
cv2.waitKey(1000)
if __name__ == "__main__":
image = cv2.imread("ceshi.png")
purpleFind(image)
orangeFind(image)
yellowFind(image)
brownFind(image)
blueFind(image)
redFind(image)
C++代码:
// coloranalyze.cpp : 此文件包含 “main” 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include
#include
#include
#include
using namespace std;
using namespace cv;
double purpleFind(Mat image);
double orangeFind(Mat image);
double yellowFind(Mat image);
double brownFind(Mat image);
double blueFind(Mat image);
double redFind(Mat image);
struct returnData
{
double colorNumber[10];
double line_y[10];
};
int main()
{
Mat srcImage = imread("D:\\code\\code\\ceshi.png");
Mat srcImage1;
cvtColor(srcImage, srcImage1, COLOR_BGR2HSV);
double y0, y1, y2, y3, y4, y5;
returnData colorline;
y0 = purpleFind(srcImage1);
colorline.colorNumber[0] = 0;
colorline.line_y[0] = y0;
y1 = orangeFind(srcImage1);
colorline.colorNumber[1] = 1;
colorline.line_y[1] = y1;
y2 = yellowFind(srcImage1);
colorline.colorNumber[2] = 2;
colorline.line_y[2] = y2;
y3 = brownFind(srcImage1);
colorline.colorNumber[3] = 3;
colorline.line_y[3] = y3;
y4 = blueFind(srcImage1);
colorline.colorNumber[4] = 4;
colorline.line_y[4] = y4;
y5 = redFind(srcImage1);
colorline.colorNumber[5] = 5;
colorline.line_y[5] = y5;
for (int i = 0; i < 6; i++) {
cout << colorline.colorNumber[i] << endl;
cout << colorline.line_y[i] << endl;
}
return 1;
}
double purpleFind(Mat image)
{
Mat dstImage;
inRange(image, Scalar(142, 43, 46), Scalar(147, 255, 255), dstImage);
Mat s, openImage, closeImage;
s = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(dstImage, openImage, MORPH_OPEN, s, Point(-1, -1), 1);
morphologyEx(openImage, closeImage, MORPH_CLOSE, s, Point(-1, -1), 1);
vector> contours;
findContours(closeImage, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Rect rect;
rect = boundingRect(contours[0]);
int line_y;
line_y = rect.y + rect.height / 2;
cout << line_y << endl;
return line_y;
}
double orangeFind(Mat image)
{
Mat dstImage;
inRange(image, Scalar(11, 43, 46), Scalar(15, 255, 255), dstImage);
Mat s, openImage, closeImage;
s = getStructuringElement(MORPH_RECT, Size(7, 7));
morphologyEx(dstImage, openImage, MORPH_OPEN, s, Point(-1, -1), 1);
morphologyEx(openImage, closeImage, MORPH_CLOSE, s, Point(-1, -1), 1);
vector> contours;
findContours(closeImage, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Rect rect;
rect = boundingRect(contours[0]);
int line_y;
line_y = rect.y + rect.height / 2;
cout << line_y << endl;
return line_y;
}
double yellowFind(Mat image)
{
Mat dstImage;
inRange(image, Scalar(20, 43, 46), Scalar(25, 255, 255), dstImage);
Mat s, openImage, closeImage;
s = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(dstImage, openImage, MORPH_OPEN, s, Point(-1, -1), 1);
morphologyEx(openImage, closeImage, MORPH_CLOSE, s, Point(-1, -1), 1);
vector> contours;
findContours(closeImage, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Rect rect;
rect = boundingRect(contours[0]);
int line_y;
line_y = rect.y + rect.height / 2;
cout << line_y << endl;
return line_y;
}
double brownFind(Mat image)
{
Mat dstImage;
inRange(image, Scalar(3, 43, 46), Scalar(8, 255, 255), dstImage);
Mat s, openImage, closeImage;
s = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(dstImage, openImage, MORPH_OPEN, s, Point(-1, -1), 1);
morphologyEx(openImage, closeImage, MORPH_CLOSE, s, Point(-1, -1), 1);
vector> contours;
findContours(closeImage, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Rect rect;
rect = boundingRect(contours[0]);
int line_y;
line_y = rect.y + rect.height / 2;
cout << line_y << endl;
return line_y;
}
double blueFind(Mat image)
{
Mat dstImage;
inRange(image, Scalar(102, 43, 46), Scalar(112, 255, 255), dstImage);
Mat s, openImage, closeImage;
s = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(dstImage, openImage, MORPH_OPEN, s, Point(-1, -1), 1);
morphologyEx(openImage, closeImage, MORPH_CLOSE, s, Point(-1, -1), 1);
vector> contours;
findContours(closeImage, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Rect rect;
rect = boundingRect(contours[0]);
int line_y;
line_y = rect.y + rect.height / 2;
cout << line_y << endl;
return line_y;
}
double redFind(Mat image)
{
Mat dstImage;
inRange(image, Scalar(168, 43, 46), Scalar(180, 255, 255), dstImage);
Mat s, openImage, closeImage;
s = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(dstImage, openImage, MORPH_OPEN, s, Point(-1, -1), 1);
morphologyEx(openImage, closeImage, MORPH_CLOSE, s, Point(-1, -1), 1);
vector> contours;
findContours(closeImage, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Rect rect;
rect = boundingRect(contours[0]);
int line_y;
line_y = rect.y + rect.height / 2;
cout << line_y << endl;
return line_y;
}