OpenCV图像基本处理

it2025-07-15  1

基本的图像展示

# 打开图片 # 展示模式有 # cv2.IMREAD_COLOR 彩色图片 cv2.IMREAD_GRAYSCALE 灰度图片 img = cv2.imread("资源路径",展示模式) # 打开图片, 会开启一个界面来打开图片 cv2.imshow("name", 需要展示的图片,此例子中为上面的img) # 整体展示 拼接图片来做集体展示 # 注意的是 有两个双括号 hstacks = np.hstack((图片)) # 设置展示图片关闭时间 cv2.waitKey(0) # 设置展示图片关闭按键 cv2.destroyAllWindows() # 结果图片保存 # cv2.imwrite("result1", img)

opencv读取图片的默认像素排列是BGR,和很多其他软件不一致 。

对图像的进行色值处理

# 图像阈值 # ret, dst = cv2.threshold(src,thresh,maxval,type) # src: 输入图,只能输入单通道图像,例如灰度图 # dst: 输出图 # thresh: 阈值 # maxval: 当达到type对阈值的规定时,赋予的值 # type 阈值类型 # cv2.THRESH_BINARY : 超过阈值部分取maxval , 否则取0 # cv2.THRESH_BINARY_INV : THRESH_BINARY的反转 # cv2.THRESH_TRUNC : 大于阈值部分设置为阈值,否则不变 # cv2.THRESH_TOZERO : 大于阈值部分不改变,否则为0 # cv2.THRESH_TOZERO_INV : THRESH_TOZERO的反转

注意!!只能是进行灰度处理的图片才可以进行如下操作,彩色图片由于是RGB,所以会出现一些莫名其妙的状况

图片的降噪

由于一些情况图片会有许多噪点,这时候可以使用滤波来解决 括号里的(5,5)为卷积核的大小。

# 均值滤波 blur = cv2.blur(img, (5, 5)) # cv2.imshow("blur", blur) # 方框滤波 和均值滤波相似 # normalize 选择是否归一化,则超过最大值 ,则为最大值 box = cv2.boxFilter(img, -1, (5, 5), normalize=True) # cv2.imshow("box", box) # 高斯滤波,定义范围内权重矩阵进行计算,卷积核内的数值满足高斯分布,以最靠中间 # 的值更重视 gaussian = cv2.GaussianBlur(img, (5, 5), 1) # cv2.imshow("gaussian", gaussian) # 中值滤波 取范围内排列整齐的中间值 median = cv2.medianBlur(img, 5) # cv2.imshow("median", median)

腐蚀/膨胀 操作

腐蚀操作会把大小内不相同的色值给腐蚀掉,而膨胀则反之

# 腐蚀操作 # 先给他定义卷积核的大小,以uint8格式,因为色值的取值为0-255,所以uint8 # 就足够了 kernel = np.ones((3, 3), np.uint8) # dst为图片路径,kernel为定义的大小,iterations为腐蚀的次数。 erosion = cv2.erode(dst, kernel, iterations=1) # cv2.imshow("erosion", erosion) # 膨胀操作 # dst为图片路径,kernel为定义的大小,iterations为膨胀的次数。 dilate = cv2.dilate(erosion3, kernel, iterations=1) # cv2.imshow("dilate", dilate) # 开运算 先腐蚀再膨胀 open = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 闭运算 先膨胀再腐蚀 close = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) open_close = np.hstack((open, close)) # 梯度运算 膨胀-腐蚀 gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) # cv2.imshow("gradient", gradient) # 礼帽 原始输入减去开运算 tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) # 黑帽 闭运算减去原始输入 blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) hat = np.hstack((tophat, blackhat)) # cv2.imshow("hat", hat) # 梯度算法 # Sobel算子 # # -1 0 +1 -1 -2 -1 # Gx = -2 0 +2 Gy = 0 0 0 # -1 0 +1 +1 +2 +1 # 类似高斯 离得越远 权重越低 # 梯度计算 中间值为 平行从右到左,垂直从下到上 相加 # 文件 深度 水平 垂直 Sobel算子大小 sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) # Sobel因子相加合并,处理效果会更好, 不建议直接添加,效果并不是太好 addxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) # 转为绝对值, 因为黑到白进行梯度计算的时候会出现负数 将会被opencv截断,所以需要取绝对值 sobel = cv2.convertScaleAbs(addxy) cv2.imshow("sobel", sobel) # Scharr算子 # # -3 0 +3 -3 -10 -3 # Gx = -10 0 +10 Gy = 0 0 0 # -3 0 +3 +3 +10 +3 # 类似高斯 离得越远 权重越低 # 梯度计算 中间值为 平行从右到左,垂直从下到上 相加 # 因为数值更大,比Sobel算子的效果更加明显 Scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0) Scharry = cv2.Scharr(img, cv2.CV_64F, 0, 1) # Scharr因子相加合并,处理效果会更好, 不建议直接添加,效果并不是太好 addScharrxy = cv2.addWeighted(Scharrx, 0.5, Scharry, 0.5, 0) # 转为绝对值, 因为黑到白进行梯度计算的时候会出现负数 将会被opencv截断,所以需要取绝对值 Scharr = cv2.convertScaleAbs(addScharrxy) cv2.imshow("Scharr", Scharr) # Laplacian算子 # # 0 1 0 # G = 1 -4 1 # 0 1 0 # 类似高斯 离得越远 权重越低 # 因为是靠中间值,所以对于一些噪点处理效果不好 # 由于是进行中间值比较 所以没有垂直与平行的概念 Laplacian = cv2.Laplacian(img, cv2.CV_64F, ksize=3) # 转为绝对值, 因为黑到白进行梯度计算的时候会出现负数 将会被opencv截断,所以需要取绝对值 Laplacian = cv2.convertScaleAbs(Laplacian) cv2.imshow("Laplacian", Laplacian)

边缘检测

# Canny边缘检测 # 都做了以下的事情 # 1)使用高斯滤波器,平滑图像,滤除噪声。 # 2)计算图像中每个像素点的梯度强度和方向。 # 3)应用非极大值抑制,以消除边缘检测带来的杂散响应。 # 4)应用双阈值来检测确定真实和潜在的边缘。 # 5)通过抑制孤立的弱边缘最终完成边缘检测。 # 双阈值检测 最小值 最大值 canny = cv2.Canny(img, 300, 300) # 值越大,阈值检测要求就越高,对于一些可能是边界的点 , 就进行了舍去 ,而保留了确定是边界的点,所以展示的不是特别全面。 # 反之则相反,展示的会更丰富 cv2.imshow("canny", canny)

图像金字塔

############################################ 图像金字塔 ############################################ # 高斯金字塔 # 向上采样(放大)则是每个方向扩大两倍,新增的行和列用0补充,用先前同样的内核乘以4,与放大后的图像卷积,得到近似值 # 2 0 2 0 # 2 2 0 0 0 0 # G 放大 G 2 0 2 0 # 2 2 0 0 0 0 # # 向下采样(缩小)则是将高斯内核卷积,将所有的偶数行和列舍去 # 1 2 3 2 1 # 2 4 6 4 2 1 3 1 # G 4 8 12 8 4 缩小 G 4 12 4 # 2 4 6 4 2 1 3 1 # 1 2 3 2 1 # 放大 up = cv2.pyrUp(img) # cv2.imshow("up", up) # 缩小 down = cv2.pyrDown(img) # cv2.imshow("down", down) # 放大后缩小,不建议这样的操作,因为放大缩小后的图片都是失真的,再进行两次操作,会更加失真 # 拉普拉斯(Laplacian)金字塔 # 公式: L = G - pyrUp(pyrDown(G)) # 拿原始的图片减去先缩小后放大的图片,拿到类似轮廓的图片。 Laplacian_up = cv2.pyrUp(img) Laplacian_down = cv2.pyrDown(Laplacian_up) l_i = img - Laplacian_down # cv2.imshow("l_i", l_i)

图像轮廓

############################################ 图像轮廓 ############################################ # 为了取轮廓的精度,一般将图片转为二值图,并且用阈值进行二值处理。 img2 = cv2.imread("demo4.png") # 转为二值图 color2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) _, color2 = cv2.threshold(color2, 127, 255, cv2.THRESH_BINARY) # 画出轮廓点: 轮廓点list格式存储 contours, _ = cv2.findContours(color2, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE) # mode: 轮廓检索模式 # cv2.RETR_EXTERNAL: 只检索最外面的轮廓 # cv2.RETR_LIST: 检索所有的轮廓,并将其保存在一条链表中 # cv2.RETR_CCOMP: 检索所有的轮廓,并将它们的组织分为两层,顶层是各部分的外部边界,第二层是空洞的边界 # cv2.RETR_TREE: 检索所有的轮廓,并重构嵌套轮廓的整个层次 # method: 轮廓逼近方法 # cv2.CHAIN_APPROX_NONE: 以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列) # cv2.CHAIN_APPROX_SIMPLE: 压缩水平的、垂直的和斜的部分,也就是,函数值保留他们的终点部分 # 复制图片, 因为画轮廓会在原有的图片进行更改 img3 = img2.copy() # 画轮廓 : 需要加轮廓的图片, 轮廓点, 轮廓索引, 轮廓颜色, 轮廓粗细 # 索引为-1 则是画出所有的轮廓。从0开始 ,到list数组最大下标,可以展示每个轮廓 res = cv2.drawContours(img3, contours, -1, (145, 53, 59), 3) # cv2.imshow("res", res) # contourArea计算面积的函数 print(cv2.contourArea(contours[5])) # 近似轮廓 # arcLength计算周长, True表示是闭合的 ,反之则相反。 arc = 0.035*cv2.arcLength(contours[5], True) # 获取近似轮廓点 approx = cv2.approxPolyDP(contours[5], arc, True) arc_img = img2.copy() # 进行近似轮廓点绘制 arc_res = cv2.drawContours(arc_img, [approx], -1, (1, 13, 43), 3) # cv2.imshow("arc_res", arc_res) # 边界矩形 x, y, w, h = cv2.boundingRect(contours[5]) rec = cv2.rectangle(arc_img, (x-10, y-10), (x+w+10, y+h+10), (0, 233, 132), 2) cv2.imshow("rec", rec)
最新回复(0)