+
15
-

回答

有三种不同的方法,从最简单经典的方法到更具艺术感的方法。

首先,请确保您已经安装了必要的库。如果尚未安装,请打开终端或命令提示符运行:

pip install opencv-python numpy matplotlib

opencv-python: 核心的图像处理库。

numpy: OpenCV 依赖它进行高效的数组运算。

matplotlib: 用于方便地在脚本中展示处理前后的图片。

方法一:经典边缘检测法 (Canny Edge Detection)

这是最基础、最直接的方法。它的原理是找出图像中亮度变化剧烈的区域,即“边缘”,然后将这些边缘以线条的形式呈现。

核心步骤:

读取图片并转为灰度图:边缘检测不关心颜色,只关心亮度变化。

高斯模糊去噪:减少图像中的噪点,防止算法将噪点误判为边缘。

Canny 边缘检测:应用 Canny 算法提取出轮廓线。

800_auto

颜色反转:Canny 算法默认生成的是“白线黑底”的图,我们需要反转成“黑线白底”才符合线稿的习惯。

代码实现:

import cv2
import matplotlib.pyplot as plt

def image_to_canny_line_art(image_path):
    """
    使用 Canny 边缘检测将图片转换为线稿图。
    """
    # 1. 读取图片并转为灰度图
    img = cv2.imread(image_path)
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 2. 高斯模糊去噪
    # (kernel_size, sigmaX),kernel_size 必须是奇数
    blurred_img = cv2.GaussianBlur(gray_img, (5, 5), 0)

    # 3. Canny 边缘检测
    # threshold1 和 threshold2 是阈值,可以调整以改变细节程度
    # 较低的阈值会检测到更多、更细微的边缘
    edges = cv2.Canny(blurred_img, threshold1=50, threshold2=150)

    # 4. 颜色反转 (黑底白线 -> 白底黑线)
    line_art = cv2.bitwise_not(edges)

    return img, line_art

# --- 主程序 ---
if __name__ == '__main__':
    input_image_path = 'your_image.jpg'  # <--- 在这里替换成你的图片路径

    original, canny_result = image_to_canny_line_art(input_image_path)

    # 使用 Matplotlib 展示结果
    plt.figure(figsize=(10, 5))

    # 显示原图 (注意 OpenCV BGR -> Matplotlib RGB)
    plt.subplot(1, 2, 1)
    plt.imshow(cv2.cvtColor(original, cv2.COLOR_BGR2RGB))
    plt.title('Original Image')
    plt.axis('off')

    # 显示线稿图
    plt.subplot(1, 2, 2)
    plt.imshow(canny_result, cmap='gray')
    plt.title('Canny Line Art')
    plt.axis('off')

    plt.tight_layout()
    plt.show()

    # 如果想保存图片
    # cv2.imwrite('line_art_canny.jpg', canny_result)

效果:线条干净、清晰,但可能缺少一些艺术感和明暗过渡。

方法二:艺术素描法 (Dodge and Burn)

这种方法模拟了摄影暗房中的“减淡与加深”技术,能够创造出更像手绘铅笔素描的效果,带有自然的阴影过渡。

800_auto

核心步骤:

转为灰度图

反相灰度图:将灰度图的颜色反转(黑变白,白变黑)。

模糊反相图:对反相后的图像进行高斯模糊。

颜色减淡混合:将原始灰度图与模糊后的反相图进行“颜色减淡”混合。这一步是精髓,它会将两张图中对应像素的值相除,能够神奇地突出轮廓,并产生素描的笔触感。

代码实现:

import cv2
import matplotlib.pyplot as plt

def image_to_sketch_art(image_path):
    """
    使用颜色减淡技术将图片转换为艺术素描图。
    """
    # 1. 读取图片并转为灰度图
    img = cv2.imread(image_path)
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 2. 反相灰度图
    inverted_gray_img = 255 - gray_img

    # 3. 模糊反相图
    # 这里的 kernel_size 可以调大一些,模糊程度越高,线条感越强
    blurred_img = cv2.GaussianBlur(inverted_gray_img, (21, 21), 0)

    # 4. 再次反相模糊图 (可选,但通常效果更好)
    inverted_blurred_img = 255 - blurred_img

    # 5. 颜色减淡混合
    # 使用 cv2.divide 可以安全地处理除以零的情况
    sketch_img = cv2.divide(gray_img, inverted_blurred_img, scale=256.0)

    return img, sketch_img


# --- 主程序 ---
if __name__ == '__main__':
    input_image_path = 'your_image.jpg'  # <--- 在这里替换成你的图片路径

    original, sketch_result = image_to_sketch_art(input_image_path)

    # 展示结果
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.imshow(cv2.cvtColor(original, cv2.COLOR_BGR2RGB))
    plt.title('Original Image')
    plt.axis('off')

    plt.subplot(1, 2, 2)
    plt.imshow(sketch_result, cmap='gray')
    plt.title('Pencil Sketch Art')
    plt.axis('off')

    plt.tight_layout()
    plt.show()

    # 保存图片
    # cv2.imwrite('line_art_sketch.jpg', sketch_result)

效果:非常接近真实的铅笔素描,有丰富的明暗层次和细腻的线条感。

方法三:风格化滤镜法 (OpenCV 内置功能)

800_auto

OpenCV 提供了一些高级的内置函数,可以直接将图像风格化,其中包括生成线稿和水彩画等效果。

核心函数: cv2.pencilSketch()

这个函数封装了复杂的算法,可以一键生成两种风格的素描:

灰度素描

彩色素描

代码实现:

import cv2
import matplotlib.pyplot as plt

def image_to_stylized_sketch(image_path):
    """
    使用 OpenCV 内置的 pencilSketch 函数生成线稿。
    """
    img = cv2.imread(image_path)

    # sigma_s: 控制图像平滑的范围,值越大,效果越像水彩画 (0-200)
    # sigma_r: 控制边缘保留程度 (0-1)
    # shade_factor: 控制阴影的强度 (0-0.1)

    # 生成灰度素描
    dst_gray, dst_color = cv2.pencilSketch(img, 
                                           sigma_s=60, 
                                           sigma_r=0.07, 
                                           shade_factor=0.05)

    return img, dst_gray, dst_color

# --- 主程序 ---
if __name__ == '__main__':
    input_image_path = 'your_image.jpg'  # <--- 在这里替换成你的图片路径

    original, gray_sketch, color_sketch = image_to_stylized_sketch(input_image_path)

    # 展示结果
    plt.figure(figsize=(15, 5))

    plt.subplot(1, 3, 1)
    plt.imshow(cv2.cvtColor(original, cv2.COLOR_BGR2RGB))
    plt.title('Original Image')
    plt.axis('off')

    plt.subplot(1, 3, 2)
    plt.imshow(gray_sketch, cmap='gray')
    plt.title('Grayscale Sketch')
    plt.axis('off')

    plt.subplot(1, 3, 3)
    plt.imshow(cv2.cvtColor(color_sketch, cv2.COLOR_BGR2RGB))
    plt.title('Color Sketch')
    plt.axis('off')

    plt.tight_layout()
    plt.show()

    # 保存图片
    # cv2.imwrite('line_art_gray_sketch_cv.jpg', gray_sketch)
    # cv2.imwrite('line_art_color_sketch_cv.jpg', color_sketch)

效果:非常具有艺术感,线条流畅,可以方便地生成彩色线稿,通过调整参数可以获得不同的艺术风格。

第四:使用边缘检测(Canny + 高斯模糊)——经典线稿

import cv2

# 读取图像
img = cv2.imread('input.jpg')

# 转为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 高斯模糊(降噪)
blur = cv2.GaussianBlur(gray, (5, 5), 0)

# 边缘检测
edges = cv2.Canny(blur, 50, 150)

# 反色,得到白底黑线的线稿
sketch = 255 - edges

# 保存结果
cv2.imwrite('sketch.png', sketch)

效果:清晰的黑白线稿,适合漫画风格。

800_auto

第五:图像取反 + 混合(模拟铅笔素描)

800_auto

import cv2

img = cv2.imread('input.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 图像取反并模糊
inv_gray = 255 - gray
blur = cv2.GaussianBlur(inv_gray, (15, 15), 0)

# 颜色减淡混合(Dodge Blend)模拟素描
sketch = cv2.divide(gray, 255 - blur, scale=256)

cv2.imwrite('pencil_sketch.png', sketch)

效果:柔和的铅笔素描风格,有明暗层次。

网友回复

我知道答案,我要回答