[学习笔记]opencv

· · 个人记录

[学习笔记]OpenCV

基于Python,By Laoair

基础操作

图片读取

# 一个是打开图片文件,一个是打开图片数据类型的对象
def readImg(src,code): ## code:0,grey;1,color
    img = cv2.imread('./img/1.jpg', code)
    cv2.imshow('test', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
def showImg(img):
    cv2.imshow('test', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
void readImg(src,code=1)
{
    Mat img = imread(src,code);
    imshow(winName,img);
    waitKey(0);
    destroyAllWindows();
}
void showImg(Mat img,string winName="test")
{
    imshow(winName,img);
    waitKey(0);
    destroyAllWindows();
}

视频读取

def readVideo(src,code):## code:6,grey;1,color
    vc = cv2.VideoCapture(src)
    if vc.isOpened():
        open,frame = vc.read()
    else:
        open = False
    while open:
        ret, frame = vc.read()
        if frame is None:
            break
        if ret == True:
            value = cv2.cvtColor(frame,code)
            cv2.imshow('result',value)
            if cv2.waitKey(10) & 0xFF ==27:
                break
    vc.release()
    cv2.destroyAllWindows()
VideoCapture cap(src);
Mat frame;
while (1)
{
    cap >> frame;
    //cap.read(frame)
    if (img.empty())break;
    imshow("img", img);
    if (27 == waitKey(20))break;
}
cap.release();//释放资源

摄像头帧率

def fpsShow(src):
    cap = cv2.VideoCapture(src)  # 导入的视频所在路径
    start_time = time.time()
    counter = 0
    fps = cap.get(cv2.CAP_PROP_FPS)  # 视频平均帧率
    while cap.isOpened():
        ret, frame = cap.read()

        counter += 1  # 计算帧数
        if (time.time() - start_time) != 0:  # 实时显示帧数
            cv2.putText(frame, "FPS {0}".format(float('%.1f' % (counter / (time.time() - start_time)))), (20, 50),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255),
                        3)
            cv2.imshow('frame', frame)
            print("FPS: ", counter / (time.time() - start_time))
            counter = 0
            start_time = time.time()
        time.sleep(1 / fps)  # 按原帧率播放

        # 键盘输入空格暂停,输入q退出
        key = cv2.waitKey(1) & 0xff
        if key == ord(" "):
            cv2.waitKey(0)
        if key == 27:
            break

    cap.release()
    cv2.destroyAllWindows()
vc = cv2.VideoCapture(0)
fps = vc.get(cv2.CAP_PROP_FPS)
print(fps)

图片截取

def cropImg(img,x1,x2,y1,y2):
    cimg=img[x1:x2,y1:y2]
    return cimg

颜色提取

def splitColor(img):
    b,g,r=cv2.split(img)
    return b,g,r
vector<Mat>channels;
split(img,channels);//通道分离
Mat blue=channels.at(0);
Mat green=channels.at(1);
Mat red=channels.at(2);

颜色设置

def imgResetColor(img,color):# color:0,b;1,g;2,r
    img[:,:,color]=0
    return img

图层合并

def imgMerge(b,g,r):
    img=cv2.merge((b,g,r))
    return img
merge(channels,dst);

边界填充

def imgFillBorder(img,top,bottom,left,right,type):# type 是 已被定义的宏
    cv2.copyMakeBorder(img,top,bottom,left,right,type)
    return img

数值计算

addWeighted(img1,0.5,img2,0.5,0,dst);

dst=5*img1;//增加曝光
dst=img1/5;//降低曝光
bitwise_and(img1,img2,dst);//逻辑与,求交集
bitwise_or(img1,img2,dst);//逻辑或,求并集
bitwise_not(img1,dst);//逻辑非,求补集
bitwise_xor(img1,img2,dst);//异或,相同为0,相异为1

ROI

img = img(Range(30,400),Range(30,400));
img = img(Rect(10,20,300,500));

图片尺寸

resize(src,dst,Size(300,300));

形态学

应用

卷积核

Mat element=getStructuringElement(MORPH_RECT,Size(5,5)); 
Mat element2=getStructuringElement(MORPH_CROSS,Size(5,5));
Mat element3=getStructuringElement(MORPH_ELLIPSE,Size(5,5));

腐蚀

def imgErosiion(img):
    kernel = np.ones( (5,5) ,np.uint8 )
    erosion = cv2.erode(img,kernel,iterations=1) # iterations 操作次数
    return erosion
erode(src,dst,element,Point(-1,-1),2);//腐蚀两次 (-1,-1)默认中心位置

膨胀

def imgDilate(img):
    kernel = np.ones((5, 5), np.uint8)
    dilate = cv2.dilate(img, kernel, iterations=1)
    return dilate
dilate(src,dst,element,Point(-1,-1),1); // 膨胀一次

开运算与闭运算

梯度运算

def imgGradient(img):
    kernel = np.ones((7,7), np.uint8)
    gradient = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
    return gradient
morphologyEx(srcImg, dstImg, MORPH_GRADIENT, element);  //形态学梯度运算

礼(顶)帽与黑帽

Sobel算子

def imgSobel(img,dx,dy):
    sobel=cv2.Sobel(img,cv2.CV_64F,dx,dy,ksize=3)
    sobel=cv2.convertScaleAbs(sobel) # 取绝对值
    return sobel
Sobel(src, dst_x, CV_16S, 1, 0, 3);
Sobel(src, dst_y, CV_16S, 0, 1, 3);
convertScaleAbs(dst_x, abs_grad_x);
convertScaleAbs(dst_y, abs_grad_y);
addWeighted(abs_grad_x 0.5, abs_grad_y, 0.5, 0, dst);

Scharr算子

def imgScharr(img,dx,dy):
    scharr = cv2.Scharr(img,cv2.CV_64F,dx,dy)
    scharr = cv2.convertScaleAbs(scharr)
    return scharr

Laplacian算子

def imgLaplacian(img):
    laplacian = cv2.Laplacian(img,cv2.CV_64F)
    laplacian = cv2.convertScaleAbs(laplacian)
    return laplacian
Laplacian(src, dst, CV_16S, 3);
convertScaleAbs(dst, abs_dst);

平滑处理

均值滤波

# 当normalize=True时,二者完全按相同;溢出会归一化
def imgBlur(img,dx,dy):
    blur = cv2.blur(img,(dx,dy))
    return blur
def imgBox(img,dx,dy):
    box = cv2.boxFilter(img,-1,(dx,dy),normalize=True)# 第二个参数指定-1为与源数据相同;第四个参数是是否取均值,不取均值可能导致数据溢出
    return box
boxFilter(src,dst,-1,Size(3,3),Point(-1,-1),true);
blur(src,dst,Size(5,5));

高斯滤波

def imgAussian(img,dx,dy):
    aussian = cv2.GaussianBlur(img,(dx,dy),1)# 第三个参数 高斯滤波器的尺寸
    return aussian
GaussianBlur(src,dst,Size(5,5),1);

中值滤波

def imgMedian(img,ksize):
    median = cv2.medianBlur(img,ksize)
    return median
medianBlur(src,dst,5);

双边滤波

bilateralFilter(src,dst,5,10.0,2.0);

阈值(二值化)

threshold(src,dst,100,255,CV_THRESH_BINARY);
adaptiveThreshold(src,dst,255,CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY,11,5); //求均值
adaptiveThreshold(src,dst,255,CV_ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY,11,5); // 加权求平均

Canny边缘检测

edges = cv2.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
'''
--------------param---------------
image: 图片源,只能是单通道图像
threshold1:低阈值
threshold2:高阈值
apertureSize:算子大小
L2gradient:为计算图像梯度幅度的标识。其默认值为 False。如果为 True,则使用更精确的 L2 范数进行计算(即两个方向的导数的平方和再开方),否则使用 L1 范数(直接将两个方向导数的绝对值相加)。
edges: 二值图
----------------------------------

---------------note---------------
----注意阈值越高,对边界的要求就越高----
----降低阈值可以得到更精细的边界图片----
----------------------------------
'''
Canny(srcImg, dstImg, 30, 80);

轮廓

img = cv2.imread(imgSrc2)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 转灰度图片
ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) # 转二位图,提高精确度 
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) # 轮廓检测

# 绘制轮廓 
drawImg = img.copy()
res = cv2.drawContours(drawImg,contours,-1,(0,0,255),2)
showImg(res)

# 轮廓近似
cnt = contours[2] # 取出某一个轮廓信息
epsilon = 0.15*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon ,True)
drawImg = img.copy()
res = cv2.drawContours(drawImg,[approx],-1,(0,0,255),2)
# showImg(res)

# 轮廓边框
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
# showImg(img)
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(srcImg, contours, hierarchy,RETR_LIST, CHAIN_APPROX_SIMPLE ); //查找所有轮廓
drawContours(tempImg, contours,-1, Scalar(0, 255, 0),2);  //绘制轮廓:-1代表绘制所有轮廓

// 遍历轮廓每一个点
for(int i=0; i<contours.size(); i++)
    for(int j=0; j<contours[i].size(); j++)
        circle(temp,Point(contours[i][j].x,contours[i][j].y),3,Scalar(0,255,0),2,8); 
# 轮廓 本质上是 点集
# 而 opencv 有很多专门处理 点集 的函数
----------------1--------------------
area = cv2.contourArea(cnt)
# 计算轮廓面积
----------------2--------------------
perimeter = cv2.arcLength(cnt,True)
# 轮廓周长
# 第二个参数用来指定对象的形状是闭合(True)还是打开(False)
----------------3--------------------
epsilon = 0.1*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
# 轮廓近似
# epsilon表示从原始轮廓到近似轮廓的最大距离,它是一个准确度参数
# epsilon越小,近似图像越复杂,也就越契合源图像
# 第三个参数True为闭合
# approxPolyDP的返回值也为 点集 , 但是近似图形的 顶点列表 
# 近似图像 点与点直接肯定是图像 ,所以返回顶点列表即可
-----------------4---------------------
(x, y, w, h) = cv2.boundingRect(cnt)
# 获得一个图像的最小矩形边框一些信息
# 返回一个元组,包含 左上角顶点的(x,y)和矩形的宽高

矩(Moments)

img = cv2.imread(imgSrc2,0)
thresh = cv2.threshold(img,110,255,cv2.THRESH_BINARY_INV)[1]
cnts= (cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE))[0]

M = cv2.moments(cnts[0])
cx,cy=int(M['m10']/M['m00']),int(M['m01']/M['m00'])
cv2.circle(img,(cx,cy),4,(130,170,0),3)
showImg(img)

直线拟合

# 注意!此代码的 几何中心 有误差!
#--------------------------------------------------------------------#
img = cv2.imread(imgSrc5)
# img = img[ int(0.3*img.shape[0]):int(0.7*img.shape[0]) ,:]
# 可以只截取一部分来拟合,提高精确度
showImg(img)
img_width = img.shape[1]
img_height = img.shape[0]

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
thres = cv2.threshold(gray,100,255,cv2.THRESH_BINARY_INV)[1]
element=np.ones((4,4), np.uint8)
thres = cv2.morphologyEx(thres, cv2.MORPH_ERODE, element)
element=np.ones((2,2), np.uint8)
thres=cv2.morphologyEx(thres, cv2.MORPH_DILATE, element)
thres=cv2.morphologyEx(thres, cv2.MORPH_ERODE, element)
v = cv2.Canny(thres, 30, 80)

# 获取点集
points = []
for y in range(img_height):
    for x in range(img_width):
        if v[y,x]==255 :
            points.append([x,y])
points = np.array(points)

output = cv2.fitLine(points, cv2.DIST_L2, 0, 0.01, 0.01)
k = output[1] / output[0]
b = output[3] - k * output[2]
p1 = ( 0 , int(k*(0-output[2])+output[3]) )
p2 = ( int(img_width-1) , int(k*(img_width-1-output[2])+output[3]) )  #
cv2.line(img,p1,p2,(0,0,255),2)

M = cv2.moments(points,True)
cx,cy = int(M['m10']/M['m00']) , int(M['m01']/M['m00'])
cv2.circle(img,(cx,cy),4,(130,170,0),-1,8)

showImg(img)

模板匹配

img = cv2.imread(imgSrc4)
tmp = cv2.imread(imgSrc5)
h,w = tmp.shape[:2]
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
tmpGray = cv2.cvtColor(tmp,cv2.COLOR_BGR2GRAY)

res = cv2.matchTemplate(imgGray,tmpGray,cv2.TM_CCOEFF_NORMED)

# 单个匹配
minval,maxvak,minloc,maxloc = cv2.minMaxLoc(res)
top_left = minloc
bottom_right = (top_left[0]+w,top_left[1]+h)
cv2.rectangle(img,top_left,bottom_right,(0,0,255),2)
showImg(img)

# 多个匹配
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
    bottom_right = (pt[0]+w,pt[1]+h)
    cv2.rectangle(img , pt , bottom_right, (0,0,255), 1)
showImg(img)
matchTemplate(src,temp,result,CV_TM_CCOEFF_NORMED);
normalize(result,result,0,1,NORM_MINMAX,-1);//归一化到0-1范围
// 单个匹配
minMaxLoc(result,&minValue,&maxValue,&minLoc,&maxLoc);
rectangle(dst,maxLoc,Point(maxLoc.x+temp.cols,maxLoc.y+temp.rows),Scalar(0,255,0),2,8);
// 多个匹配
if(maxValue>=0.7)
    rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2);

Trackbar

# 二值化调试
def update(x):
    thres = cv2.getTrackbarPos('Threshold','test')
    res=cv2.threshold(img,thres,255,cv2.THRESH_BINARY)[1]
    cv2.imshow('test',res)

img = cv2.imread(imgSrc1,0)
cv2.namedWindow('test')
thres = 100
cv2.createTrackbar('Threshold','test', thres ,255,update)
update(0)
cv2.waitKey(0)
cv2.destroyAllWindows()

# HSV 调试
def onTrackbar(x):
    minh, mins, minv = cv2.getTrackbarPos('minh', 'test'), \
                       cv2.getTrackbarPos('mins', 'test'), \
                       cv2.getTrackbarPos('minv', 'test')
    maxh, maxs, maxv = cv2.getTrackbarPos('maxh', 'test'), \
                       cv2.getTrackbarPos('maxs', 'test'), \
                       cv2.getTrackbarPos('maxv', 'test')
    color1 = (minh,mins,minv)
    color2 = (maxh,maxs,maxv)
    print(color1,color2)
    res = cv2.inRange(img, color1, color2)
    cv2.imshow('test',res)

orig = cv2.imread(imgSrc4)
img = cv2.cvtColor(orig,cv2.COLOR_BGR2HSV)
showImg(img)
minh,mins,minv = 0,0,0
maxh,maxs,maxv = 255,255,255

color1 = (minh,mins,minv)
color2 = (maxh,maxs,maxv)

cv2.namedWindow('test')
cv2.createTrackbar('minh','test', minh ,255,onTrackbar)
cv2.createTrackbar('mins','test', mins ,255,onTrackbar)
cv2.createTrackbar('minv','test', minv ,255,onTrackbar)
cv2.createTrackbar('maxh','test', maxh ,255,onTrackbar)
cv2.createTrackbar('maxs','test', maxs ,255,onTrackbar)
cv2.createTrackbar('maxv','test', maxv ,255,onTrackbar)

onTrackbar(0)
cv2.waitKey(0)
cv2.destroyAllWindows()
void onChange(int, void* param)
{
    Mat img = *(Mat *)param;
    Mat dst;
    threshold(img,dst,thr,255,THRESH_BINARY);
    imshow("test",dst);
}
int main()
{
    string src = "img/1.jpg";
    Mat img = imread(src,1);
    namedWindow("test",WINDOW_NORMAL);
    createTrackbar("Threshold","test",&thr,255,onChange,&img);
    imshow("test",img);
    waitKey(0);
}

绘图

plt.plot(x, y, format_string, kwargs)
'''
普通画图
x:x轴数据,列表或数组,可选
y:y轴数据,列表或数组
format_string:控制曲线的格式字符串,可选,由颜色字符、风格字符和标记字符组成。
'''
plt.xlim(x,y) 
'''
设置直方图显示的x坐标范围
显示的是x轴的作图范围,右端点为开区间
也可以 赋值列表
'''
plt.hist(
x, bins=10, range=None, normed=False,
weights=None, cumulative=False, bottom=None,
histtype=u'bar', align=u'mid', orientation=u'vertical',
rwidth=None, log=False, color=None, label=None, stacked=False,
hold=None, **kwargs)
'''
画图,可以一次性把各参数设置好
x:数据 ,n维数组
bin:箱子的个数
粗暴的使用就是赋值数据即可
'''
plt.imshow(img,'gray')
'''
在 plt 窗口中显示一张图片
'''
img = cv2.imread(imgSrc0)
cv2.circle(img,(50,50),20,(0,0,255))
cv2.line(img,(30,90),(90,30),(0,255,0))
cv2.rectangle(img,(20,80),(80,300),(255,0,0))
cv2.putText(img,"Hello",(30,30),cv2.FONT_HERSHEY_SIMPLEX,1,(255,255,0));
showImg(img)
circle(img,Point(200,200),100,(0,255,0),5,8);
circle(img,Point(200,200),100,(0,255,0),-1,8);//-1画实心圆
line(img,Point(10,10),Point(100,250),Scalar(0,0,255),5,8);
rectangle(img,Point(300,300),Point(500,600),Scalar(255,0,0),3,8);
rectangle(img,Rect(500,500,100,100),Scalar(0,0,255),3,8);
putText(img,"china",Point(100,100),FONT_HERSHEY_COMPLEX,1,Scalar(0,0,255),1);

直方图

绘制直方图

mask 操作

img = cv2.imread(imgSrc1,0)
mask = np.zeros(img.shape[:2],np.uint8) # 与原图大小保持一致
mask[100:300,100:400] = 255
showImg(mask)

masked_img = cv2.bitwise_and(img,img,mask=mask) # 两个img与运算 然后只输出掩膜部分
showImg(masked_img)

均衡化

equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
plt.show()

自适应均衡化

img = cv2.imread(imgSrc1,0)

# 自适应均衡化
clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8)) # 默认设置
res_clahe = clahe.apply(img)

# 全局均衡化
equ = cv2.equalizeHist(img)

res = np.hstack((res_clahe,equ))
showImg(res)

多线程

import threading
lock = threading.Lock()

lock.acquire()
v1 = readVideo(0)
lock.release()

lock.acquire() # 拿到锁了才会继续执行 ,拿不到就卡在这里
v2 = readVideo(1)
lock.release()

Zbar

# barcodes内容
barcodes =  [Decoded(data=b'Hello Python',
                     type='QRCODE',
                     rect=Rect(left=430, top=30, width=340, height=340),
                     polygon=[Point(x=430, y=30),
                              Point(x=430, y=368),
                              Point(x=770, y=370),
                              Point(x=768, y=30)],
                     quality=1,
                     orientation='UP'),
             Decoded(data=b'Hello Zbar',
                     type='QRCODE',
                     rect=Rect(left=30, top=30, width=340, height=340),
                     polygon=[Point(x=30, y=30),
                              Point(x=30, y=368),
                              Point(x=370, y=370),
                              Point(x=368, y=30)],
                     quality=1,
                     orientation='UP')]
# 示范代码
import pyzbar.pyzbar as pyzbar
img1 = cv2.imread("img/Hello+Zbar.png")
img2 = cv2.imread("img/Hello+Python.png")
img = np.hstack((img1,img2))
showImg(img)

barcodes = pyzbar.decode(img)
for barcode in barcodes:
    data = barcode.data.decode("utf-8")
    type = barcode.typy
    text = "data:{}\ntype:{}".format(data,type)
    print(text)
for barcode in barcodes:
    points = barcode.polygon # 左上角 左下角 右下角 右上角
    k = 5
    point0 = (points[0][0]-k,points[0][1]-k)
    point1 = (points[1][0]-k,points[1][1]+k)
    point2 = (points[2][0]+k,points[2][1]+k)
    point3 = (points[3][0]+k,points[3][1]-k)
    cv2.circle(img, point0, 2, (0, 0, 255))
    cv2.circle(img, point1, 2, (0, 0, 255))
    cv2.circle(img, point2, 2, (0, 0, 255))
    cv2.circle(img, point3, 2, (0, 0, 255))
showImg(img)

傅里叶变换

img = cv2.imread(imgSrc2,0)
showImg(img)
img_float32 = np.float32(img)

dft = cv2.dft(img_float32,flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
magnitude_spectrum = (magnitude_spectrum ).astype(np.uint8) # 转换为 图像数据 的存储格式 uint8
showImg(magnitude_spectrum)

plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.show()
img = cv2.imread(imgSrc2,0)
showImg(img)
img_float32 = np.float32(img)

# 傅里叶变换
# cv2.dft() 返回的结果是双通道的 ( 实部,虚部 ),通常还需要转换成图像格式才能展示(0,255)像素值
dft = cv2.dft(img_float32,flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

rows,cols = img.shape
crow,ccol = int(rows/2),int(cols/2) # 得到中心位置

# 低通滤波
mask_low = np.zeros((rows,cols,2),np.uint8) # 注意是三维的!
mask_low[crow-30:crow+30,ccol-30:ccol+30]=1 # 只保留中心周围的点

# 高通滤波
mask_high = np.ones((rows,cols,2),np.uint8) # 注意是三维的!
mask_high[crow-30:crow+30,ccol-30:ccol+30]=0 # 只保留中心周围的点

mask = mask_low # 选择滤波器

# 傅里叶逆变换
fshift = dft_shift * mask # mask 的取值是0或1
f_ishift = np.fft.ifftshift(fshift) # 将中心位置的频谱还原
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])# 还需要双通道合并
# img_back = 20*np.log(img_back)
# 对两个通道进行转换才能得到图像形式表达,由于转换后的值为非常小的数值,因此还要转换到 0-255 之间

plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Input Image'), plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img_back,cmap='gray')
plt.title('Result'),plt.xticks([]),plt.yticks([])
plt.show()

showImg(img_back)

角点检测

img = cv2.imread(imgSrc3)
showImg(img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = cv2.cornerHarris(gray,2,3,0.04)
img[dst>0.09*dst.max()] = (0,0,255)
showImg(img)

霍夫检测

# 霍夫线检测
orig = cv2.imread(imgSrc4)
img = cv2.cvtColor(orig,cv2.COLOR_BGR2HSV)

minh , mins , minv = 22 ,10,22
maxh , maxs , maxv = 136,150,121
img = cv2.inRange(img,(minh,mins,minv),(maxh,maxs,maxv))

element = cv2.getStructuringElement(cv2.MORPH_RECT, (3,6))
img = cv2.morphologyEx(img, cv2.MORPH_ERODE, element)
element = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
img = cv2.morphologyEx(img, cv2.MORPH_DILATE, element)
img = cv2.morphologyEx(img, cv2.MORPH_ERODE, element)

after_canny = cv2.Canny(img,100,200,3)
showImg(after_canny)

lines = cv2.HoughLines(after_canny, 1, np.pi/180, 160)

for line in lines:
    rho , theta = line[0][0] , line[0][1] # line 是一个数组的数组
    a , b = np.cos(theta) , np.sin(theta)
    x0 , y0 = a*rho , b*rho
    point1 = ( int(x0+1000*(-b)) , int(y0+1000*a) )
    point2 = ( int(x0-1000*(-b)) , int(y0-1000*a) )
    cv2.line(orig,point1,point2,(55,100,195),2,8)

showImg(orig)
vector<Vec2f> lines;  //定义矢量结构lines用于存放得到的线段矢量集合
HoughLines(src, lines, 1, CV_PI/180, 150);//超过150的线段才被检测到
//依次在图中绘制出每条线段
for (size_t i = 0; i < lines.size(); i++)
{
    float rho=lines[i][0],theta=lines[i][1];
    Point pt1,pt2;
    double a=cos(theta),b=sin(theta);
    double x0=a*rho,y0=b*rho;
    pt1.x=cvRound(x0+1000*(-b));//cvRound(double value) 函数:对一个double型数字四舍五入,返回一个整数
    pt1.y=cvRound(y0+1000*(a));
    pt2.x = cvRound(x0 - 1000*(-b));  
    pt2.y = cvRound(y0 - 1000*(a));  
    line(dst,pt1,pt2,Scalar(55,100,195),2,8);
}
# 霍夫圆检测
orig = cv2.imread(imgSrc1)
img = cv2.GaussianBlur(orig,(7,7),2)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thres = cv2.threshold(gray, 25, 255, cv2.THRESH_BINARY)[1]
thres = cv2.GaussianBlur(thres,(7,7),2)

circles = cv2.HoughCircles(thres,cv2.HOUGH_GRADIENT,1,20,100,80,50,0)

for circle in circles:
    center = ( int(circle[0][0]) , int(circle[0][1]) )
    radius = int(circle[0][2])
    cv2.circle(orig,center,radius,(0,0,255),2)
showImg(orig)
vector<Vec3f> circles;
HoughCircles(src, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100);
for(size_t i = 0; i<circles.size(); i++)
{
    Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
    int radius = cvRound(circles[i][2]);
    circle(dst, center, 3, Scalar(0, 0, 255), -1, 8,0);//设置为-1时,画实心圆
    circle(dst, center, radius, Scalar(0, 255, 0), 3, 8,0);//画空心圆
}

尺度空间

特征匹配

图像金字塔

高斯金字塔

up = cv2.pyrUp(img)
up = cv2.pyrUp(img)

拉普拉斯金字塔

img = cv2.imread(imgSrc1,1)
down = cv2.pyrDown(img)
up = cv2.pyrUp(down)
l = img-up
res = np.hstack((img,l))
showImg(res)