段力辉版本《OpenCV-Python 中文教程》学习
此书极好,值得借鉴学习,并且开源开放。Python在实现过程中,体现出来了非常强的优势,特别是结合Numpy来进行矩阵计算,有很多简化方法。这里将学习过程代码进行增编、添加后进行展示。
Python目前的缺点应该是缺乏一个像ImageWatch这样的工具,这将影响算法研究;另外Numpy的过度抽象,某种程度上也会造成障碍。
1、寻找指定色彩区域
Python的特色,在于Numpy的使用
import cv2
import numpy
as np
src = cv2.imread(
"e:/template/tiantan.jpg")
hsv = cv2.cvtColor(src,cv2.COLOR_BGR2HSV)
lower_blue = np.array([
100,
43,
46])
upper_blue = np.array([
124,
255,
255])
mask = cv2.inRange(hsv,lower_blue,upper_blue)
res = cv2.bitwise_and(src,src,mask=mask)
cv2.imshow(
"hsv",hsv)
cv2.imshow(
"mask",mask)
cv2.imshow(
"res",res)
cv2.waitKey(
0)
2、warpperspective 透视变化的python实现
import cv2
import numpy
as np
src = cv2.imread(
"e:/template/steel03.jpg")
rows,cols,ch = src.shape
pts1 = np.float32([[
122,
0],[
814,
0],[
22,
540],[
910,
540]])
pts2 = np.float32([[
0,
0],[
960,
0],[
0,
540],[
960,
540]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(src,M,(cols,rows))
cv2.imshow(
"src",dst)
cv2.waitKey(
0)
这里操作的核心,是一个np的矩阵。在C++中,使用Vector,可能会造成很多浪费。
3、自适应阈值
import cv2
import numpy
as np
obj = cv2.imread(
"e:/template/pig.jpg",
0)
ret,th1 = cv2.threshold(obj,
100,
255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(obj,
255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,
11,
2)
ret3,th3 = cv2.threshold(obj,
0,
255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow(
"th3",th3)
print(ret3)
cv2.waitKey()
当参数选择OTSU的时候,能够根据计算,自动算出下限。但是我认为这一点并没有什么特别的用途。
4、模糊处理
obj = cv2.imread(
"e:/template/pig.jpg",
0)
blur= cv2.blur(obj,(
3,
3))
gaussBlur=cv2.GaussianBlur(obj,(
3,
3),
0)
median = cv2.medianBlur(obj,
5)
bilate = cv2.bilateralFilter(obj,
0.75,
0.75)
5、形态学变换
obj = cv2.imread(
"e:/template/pig.jpg",
0)
opening = cv2.morphologyEx(obj,cv2.MORPH_OPEN,(
7,
7))
cv2.imshow(
"obj",obj)
cv2.imshow(
"opening",opening)
我喜欢这种写法,这将有长远影响。
6、梯度变化,包括1阶、2阶和混合的。
obj = cv2.imread(
"e:/template/pig.jpg",
0)
laplacian = cv2.Laplacian(obj,cv2.CV_64F)
sobelx=cv2.Sobel(obj,cv2.CV_64F,
1,
0,ksize=
5)
sobely=cv2.Sobel(obj,cv2.CV_64F,
0,
1,ksize=
5)
7、梯度融合
曾经这段代码很神秘的,但是今日使用Python来写,就非常简单。可以看出,Python用来处理二维矩阵信息是很强的。
# Standard imports
import cv2
import numpy
as np
A = cv2.imread(
"e:/template/apple.jpg")
B = cv2.imread(
"e:/template/orange.jpg")
G = A.copy()
gpA=[G]
for i
in range(
6):
G = cv2.pyrDown(G)
gpA.append(G)
G = B.copy()
gpB = [G]
for i
in range(
6):
G = cv2.pyrDown(G)
gpB.append(G)
lpA = [gpA[
5]]
for i
in range(
5,
0,-
1):
GE = cv2.pyrUp(gpA[i])
L = cv2.subtract(gpA[i-
1],GE)
lpA.append(L)
lpB = [gpB[
5]]
for i
in range(
5,
0,-
1):
GE = cv2.pyrUp(gpB[i])
L = cv2.subtract(gpB[i-
1],GE)
lpB.append(L)
LS = []
for la,lb
in zip(lpA,lpB):
rows,cols,dpt= la.shape
print(rows,cols)
ls = np.hstack((la[:,
0:cols//
2],lb[:,cols//
2:]))
#直接横向排列
LS.append(ls)
ls_ = LS[
0]
for i
in range(
1,
6):
ls_ = cv2.pyrUp(ls_)
ls_ = cv2.add(ls_,LS[i])
real = np.hstack((A[:,:cols//
2],B[:,cols//
2:]))
cv2.imshow(
"ls_",ls_)
cv2.imshow(
"real",real)
cv2.waitKey()
8、轮廓寻找
import cv2
import numpy
as np
src = cv2.imread(
"e:/template/rectangle.jpg")
gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,
127,
255,
0)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
print(contours)
src = cv2.drawContours(src,contours,-
1,(
0,
255,
0),
3)
cv2.imshow(
"src",src)
cv2.waitKey()
这里,使用
cv2.CHAIN_APPROX_NONE
或者不同的参数的话,会获得不同的轮廓结果。这对于我现有的轮廓分析研究,也是有帮助的。
9、轮廓的最小 接圆和最大内切圆
外接圆比较简单
(x,y),radius = cv2.minEnclosingCircle(contours[
0])
center = (int(x),int(y))
radius = int(radius)
src = cv2.circle(src,center,radius,(
0,
255,
0),
2)
注意它这里的表示方法。内切圆则采用特殊方法。
# Get the contours
contours, _ = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Calculate the distances to the contour
raw_dist = np.empty(thresh.shape, dtype=np.float32)
for i
in range(src.shape[
0]):
for j
in range(src.shape[
1]):
raw_dist[i,j] = cv.pointPolygonTest(contours[
0], (j,i),
True)
minVal, maxVal, _, maxDistPt = cv.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)
# Depicting the distances graphically
drawing = np.zeros((src.shape[
0], src.shape[
1],
3), dtype=np.uint8)
for i
in range(src.shape[
0]):
for j
in range(src.shape[
1]):
if raw_dist[i,j] <
0:
drawing[i,j,
0] =
255 - abs(raw_dist[i,j]) *
255 / minVal
elif raw_dist[i,j] >
0:
drawing[i,j,
2] =
255 - raw_dist[i,j] *
255 / maxVal
else:
drawing[i,j,
0] =
255
drawing[i,j,
1] =
255
drawing[i,j,
2] =
255
cv.circle(drawing,maxDistPt,int(maxVal),(
255,
255,
255))
cv.imshow(
'Source', src)
cv.imshow(
'Distance and inscribed circle', drawing)
cv.waitKey()
最大内接圆则复杂许多。
10、寻找轮廓的极点
contours, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[
0]
leftmost = tuple(cnt[cnt[:,:,
0].argmin()][
0])
rightmost= tuple(cnt[cnt[:,:,
0].argmax()][
0])
topmost = tuple(cnt[cnt[:,:,
1].argmin()][
0])
bottommost=tuple(cnt[cnt[:,:,
1].argmax()][
0])
cv2.circle(src,leftmost,
5,(
0,
255,
0))
cv2.circle(src,rightmost,
5,(
0,
255,
255))
cv2.circle(src,topmost,
5,(
255,
255,
0))
cv2.circle(src,bottommost,
5,(
255,
0,
0))
cv2.imshow(
"src",src)
这是一种很好的方法,能够直接找出轮廓的各方向边界。
11 模板匹配
src = cv.imread(
"e:/template/lena.jpg",
0)
template = cv.imread(
"e:/template/lenaface.jpg",
0)
w,h = template.shape
res = cv.matchTemplate(src,template,cv.TM_CCOEFF)
min_val,max_val,min_loc,max_loc = cv.minMaxLoc(res)
cv.rectangle(src,max_loc,(max_loc[
0]+w,max_loc[
1]+h),(
0,
0,
255),
2)
cv.imshow(
"template",template)
cv.imshow(
"src",src)
cv.waitKey()
我想体现的是python它的写法有很大不同。
src = cv.imread(
"e:/template/coin.jpg")
gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
template = cv.imread(
"e:/template/coincut.jpg",
0)
w,h = template.shape
res = cv.matchTemplate(gray,template,cv.TM_CCOEFF_NORMED)
threshold =
0.4
loc = np.where(res>=threshold)
print(loc)
for pt
in zip(*loc[::
1]):
cv.rectangle(src,pt,(pt[
0]+w,pt[
1]+h),(
0,
0,
255),
2)
cv.imshow(
"template",template)
cv.imshow(
"src",src)
cv.waitKey()
结合使用阈值,可以实现多目标匹配。
# Standard imports
import cv2
as cv
import numpy
as np
src = cv.imread(
"e:/template/coin.jpg")
gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
template = cv.imread(
"e:/template/coincut.jpg",
0)
w,h = template.shape
res = cv.matchTemplate(gray,template,cv.TM_CCOEFF_NORMED)
threshold =
0.6
loc = np.where(res>=threshold)
print(loc)
for pt
in zip(*loc[::-
1]):
#排序方法为height width
print(pt)
cv.rectangle(src,pt,(pt[
0]+w,pt[
1]+h),(
0,
0,
255),
2)
cv.imshow(
"template",template)
cv.imshow(
"src",src)
cv.waitKey()
特别需要注意其排序方法。但是这里的阈值选择,也是超参数类型的。
12 HoughCircle
src = cv.imread(
"e:/template/circle.jpg",
0)
src = cv.medianBlur(src,
5)
cimg = cv.cvtColor(src,cv.COLOR_GRAY2BGR)
circles = cv.HoughCircles(src,cv.HOUGH_GRADIENT,
1,
20,param1=
50,param2=
30,minRadius=
0,maxRadius=
0)
circles = np.uint16(np.around(circles))
for i
in circles[
0,:]:
cv.circle(cimg,(i[
0],i[
1]),i[
2],(
0,
255,
0),
2)
cv.circle(cimg,(i[
0],i[
1]),
2,(
0,
0,
255),
3)
cv.imshow(
"src",cimg)
cv.waitKey()
13 风水岭算法
# Standard imports
import cv2
as cv
import numpy
as np
src = cv.imread(
"e:/template/water_coins.jpg")
gray =cv.cvtColor(src,cv.COLOR_BGR2GRAY)
_,thresh = cv.threshold(gray,
0,
255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)
kernel = np.ones((
3,
3),np.uint8)
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel,iterations=
2)
sur_bg = cv.dilate(opening,kernel)
dist_transform = cv.distanceTransform(opening,
1,
5)
_,sur_fg=cv.threshold(dist_transform,
0.7*dist_transform.max(),
255,
0)
sur_fg = np.uint8(sur_fg)
unknow = cv.subtract(sur_bg,sur_fg)
_,markers1 = cv.connectedComponents(sur_fg)
markers = markers1+
1
markers[unknow ==
255] =
0
markers3 = cv.watershed(src,markers)
src[markers3 == -
1] = [
255,
0,
0]
cv.imshow(
"src",src)
cv.waitKey()
这个结果,具有参考价值。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端