【Python-图形】对不规则环形进行渐变处理

(完整代码在最下方)

一、实现:从嵌套的圈a到圈b(即环形)的所有像素颜色从颜色x渐变为颜色y。

二、应用:估测两条等高线之间每一处的具体高度。

三、简介:网上找了很多资料,但基本所有的渐变都是变化率固定的的线性变化,这样只适合规则图形。如果在不规则图形上,就会出现在a端颜色统一为x,b端却分化为颜色x和颜色z的情况。我希望做一个变化率不固定的方法出来,于是就有了以下代码:

四、过程:

1.预先准备

pip install opencv-python、pip install numpy

import cv2 as cv
import numpy as np

待处理图片

 

 2.采用OpenCV的边缘检测获取轮廓

# 【启动代码】
# 随意替换,只要能输入方法需要的参数即可

# 1.读取图像
path = '你的路径'
image = cv.imread(path)

# 2.识别颜色种类
color_values = np.unique(image)
color_values.sort()

# 3.随机挑选其中三个颜色a、b、c,画出a与b的交界线、b与c的交界线,将两个交界线作为后续步骤中进行操作的两个轮廓。
_, edge1 = cv.threshold(image, color_values[1], color_values[2], cv.THRESH_BINARY_INV)
edge1 = cv.Canny(edge1, 50, 150)
contour1, _ = cv.findContours(edge1, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

_, edge2 = cv.threshold(image, color_values[2], color_values[3], cv.THRESH_BINARY_INV)
edge2 = cv.Canny(edge2, 50, 150)
contour2, _ = cv.findContours(edge2, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
​

3.轮廓挑选

# 4.两个轮廓全部展示
contour_image = image.copy() 
cv.drawContours(contours_image, contour1, -1, (255, 0, 0), 2)
cv.drawContours(contours_image, contour2, -1, (0, 255, 0), 2)
cv.imshow("Contours", contours_image)
cv.waitKey(0)
cv.destroyAllWindows()

绿线和蓝线之间就是我们要实现渐变的区域,可以看到有四个圈,现在我们只想对右边的两个圈进行渐变。

OpenCV里的轮廓是实际上是一堆轮廓的集合,这里都取[1],取到右边的两个圈

# 5.两个轮廓中都只取其中一个部分展示
contours_image = image.copy() 
cv.drawContours(contours_image, contour1[1], -1, (255, 0, 0), 2)
cv.drawContours(contours_image, contour2[1], -1, (0, 255, 0), 2)
cv.imshow("Contour", contours_image)
cv.waitKey(0)
cv.destroyAllWindows()

 这里轮廓线断断续续应该是显示问题,后续运作是正常的

4.调用方法,输入参数

 五个参数分别是待处理图片,内轮廓、外轮廓、内颜色、外颜色。

内颜色和外颜色我随便写了深红和正红。

等下要实现的是从内轮廓的内颜色渐变到外轮廓的外颜色

# 6.将轮廓与颜色输入函数
image = draw_gradient(image,contour1[1],contour2[1],(0,0,127),(0,0,255))
cv.imshow("Result", image)
cv.waitKey(0)
cv.destroyAllWindows()

5.方法运行,得到结果

# 【方法体】

def draw_gradient(image,inner_contour,outer_contour,inner_color,outer_color):
    # 1.计算颜色差值
    # 适用于RGB等三通道图像,也可以改成别的模式
    difference = [None] * 3
    for i in range(3):
        difference[i] = inner_color[i] - outer_color[i]
    height, width = image.shape[:2]

    # 2.遍历每行每列的像素
    for y in range(height):
        for x in range(width):
            # 3. 判断是否在大轮廓内
            distance_to_outer = cv.pointPolygonTest(outer_contour, (x,y), True)
            if distance_to_outer > 0:
                # 4. 判断是否在小轮廓外
                distance_to_inner = cv.pointPolygonTest(inner_contour, (x,y), True)
                if distance_to_inner < 0:
                    # 5.若符合以上两个条件,将该点改为介于inner_color和outer_color之间的渐变颜色
                    # 5.1计算颜色比例
                    ratio = - distance_to_inner / (distance_to_outer - distance_to_inner)
                    # 5.2替换颜色
                    for i in range(3):
                        image[y,x][i] = (ratio * difference[i] + outer_color[i])
                        
    return image

最终结果如下:

可以看到,颜色并不是均匀变化的,而是由到内轮廓的距离与外轮廓的距离所决定。像素位置越接近内轮廓,其颜色就越接近内颜色,反之亦然。

五、 完整代码

import cv2 as cv
import numpy as np

# 【方法体】

def draw_gradient(image,inner_contour,outer_contour,inner_color,outer_color):
    # 1.计算颜色差值
    # 适用于RGB等三通道图像,也可以改成别的模式
    difference = [None] * 3
    for i in range(3):
        difference[i] = inner_color[i] - outer_color[i]
    height, width = image.shape[:2]

    # 2.遍历每行每列的像素
    for y in range(height):
        for x in range(width):
            # 3. 判断是否在大轮廓内
            distance_to_outer = cv.pointPolygonTest(outer_contour, (x,y), True)
            if distance_to_outer > 0:
                # 4. 判断是否在小轮廓外
                distance_to_inner = cv.pointPolygonTest(inner_contour, (x,y), True)
                if distance_to_inner < 0:
                    # 5.若符合以上两个条件,将该点改为介于inner_color和outer_color之间的渐变颜色
                    # 5.1计算颜色比例
                    ratio = - distance_to_inner / (distance_to_outer - distance_to_inner)
                    # 5.2替换颜色
                    for i in range(3):
                        image[y,x][i] = (ratio * difference[i] + outer_color[i])
                        
    return image

# 【启动代码】
# 随意替换,只要能输入方法需要的参数即可

# 1.读取图像
path = '你的路径'
image = cv.imread(path)

# 2.识别颜色种类
color_values = np.unique(image)
color_values.sort()

# 3.随机挑选其中三个颜色a、b、c,画出a与b的交界线、b与c的交界线,将两个交界线作为后续步骤中进行操作的两个轮廓。
_, edge1 = cv.threshold(image, color_values[1], color_values[2], cv.THRESH_BINARY_INV)
edge1 = cv.Canny(edge1, 50, 150)
contour1, _ = cv.findContours(edge1, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

_, edge2 = cv.threshold(image, color_values[2], color_values[3], cv.THRESH_BINARY_INV)
edge2 = cv.Canny(edge2, 50, 150)
contour2, _ = cv.findContours(edge2, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

# 4.两个轮廓全部展示
contour_image = image.copy() 
cv.drawContours(contours_image, contour1, -1, (255, 0, 0), 2)
cv.drawContours(contours_image, contour2, -1, (0, 255, 0), 2)
cv.imshow("Contours", contours_image)
cv.waitKey(0)
cv.destroyAllWindows()

# 5.两个轮廓中都只取其中一个部分展示
contours_image = image.copy() 
cv.drawContours(contours_image, contour1[1], -1, (255, 0, 0), 2)
cv.drawContours(contours_image, contour2[1], -1, (0, 255, 0), 2)
cv.imshow("Contour", contours_image)
cv.waitKey(0)
cv.destroyAllWindows()

# 6.将轮廓与颜色输入函数
image = draw_gradient(image,contour1[1],contour2[1],(0,0,127),(0,0,255))
cv.imshow("Result", image)
cv.waitKey(0)
cv.destroyAllWindows()

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值