完整代码在最后。
一、处理结果
图1 原图像(左)和上色后图像(右)
二、实现方法
Opencv中提供了五种阈值分割的函数,将这五种函数均应用于源图像观察其效果。
图2 五种阈值分割函数作用于原图像img1
图3 阈值分割结果(左上为原图像)
发现第四种方法可以分割到完整的花瓣部分并保留细节,第五种方法即第四种的取反可以分割到叶子的部分并保留细节。取这两种方法的结果,用mapcolor上色。
图4 上色算法
图5 两张图上色分开的结果
将两张彩色图片做加法。得到的结果既有花的颜色也有背景的颜色。
图6 图像相加
图7 相加结果
三、总结
1.通过分开处理背景与花朵并分开上色再相加的方法可以给原灰度图像上色,但是由于阈值分割的结果中,被分割出的部分为黑色,颜色较深,因此融合结果会变暗,最好能够搭配提高亮度的算法优化结果,但由于有些复杂我还没有实现。
2.可以发现,在阈值分割后图片中一些属于花的地方被认为是背景,尝试使用腐蚀算法,但由于腐蚀算法只能作用域二值化后的图像,而二值化会失去图像细节,因此并未将腐蚀后的结果上色。
图8 腐蚀算法
图9 腐蚀后结果
3.在初期的尝试过程中,我曾尝试不使用colormap伪彩上色,通过直方图得出阈值后,对逐个像素进行判断,小于阈值94的部分上绿色,大于94的部分是红色,但这样得到的结果并不具有观赏性。
图10 实现函数(其中blue实际上是red)
图11 结果
好看点的那个的代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_path = "C:/Users/Lenovo/PycharmProjects/color_flower/2.png"
img1 = cv2.imread('2.png', cv2.IMREAD_GRAYSCALE)
binary_path, th = cv2.threshold(img1, 180, 255, cv2.THRESH_BINARY)
binary_inv_path, th1 = cv2.threshold(img1, 180, 255, cv2.THRESH_BINARY_INV)
trunc_path, th2 = cv2.threshold(img1, 180, 255, cv2.THRESH_TRUNC)
tozero_path, th3 = cv2.threshold(img1, 180, 255, cv2.THRESH_TOZERO)
tozero_inv_path, th4 = cv2.threshold(img1, 180, 255, cv2.THRESH_TOZERO_INV)
def erode_demo(gray):
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("binary", binary)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dst = cv2.erode(binary, kernel)
return dst
def dilate_demo(gray):
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("binary", binary)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dst = cv2.dilate(binary, kernel)
return dst
result = erode_demo(th3)
result3 = dilate_demo(result)
cv2.imshow('result', result)
cv2.imshow('result3',result3)
cv2.waitKey(0)
cv2.destroyAllWindows()
img_color = cv2.applyColorMap(th3, cv2.COLORMAP_HOT)
img_color1 = cv2.applyColorMap(th4, cv2.COLORMAP_DEEPGREEN)
Image = cv2.addWeighted(img_color, 0.3, img_color1, 0.7, 0)
out_img1 = np.hstack((img1, th, th1))
out_img2 = np.hstack((th2, th3, th4))
out_img = np.vstack((out_img1, out_img2))
cv2.imwrite("C:/Users/Lenovo/PycharmProjects/color_flower/out.png", out_img)
cv2.imwrite("C:/Users/Lenovo/PycharmProjects/color_flower/out1.png", img_color)
cv2.imwrite("C:/Users/Lenovo/PycharmProjects/color_flower/out2.png", img_color1)
cv2.imwrite("C:/Users/Lenovo/PycharmProjects/color_flower/out3.png", Image)
替换像素直接上色的代码:
import cv2
import matplotlib.pyplot as plt
import numpy as np
import math
import os
import pandas as pd
from tqdm import tqdm
# 绘制直方图函数
'''def grayHist(img):
h, w = img.shape[:2]
pixelSequence = img.reshape([h * w, ])
numberBins = 256
histogram, bins, patch = plt.hist(pixelSequence, numberBins,facecolor='black', histtype='bar')
plt.xlabel("gray label")
plt.ylabel("number of pixels")
plt.axis([0, 255, 0, np.max(histogram)])
plt.show()
image = cv2.imread("1.jpg",0)
grayHist(image)'''
color_dict = {"green": [34, 139, 34],
"blue": [255,0,255],
"pink": [203, 192, 255]}
#img = cv2.imread('1.jpg')
img = cv2.imread('../flower2/1.jpg', cv2.IMREAD_GRAYSCALE)
#img_color = gray2rgb(gray , color_dict)
def gray2rgb(gray, color_dict):
# 1:创建新图像容器
rgb_image = np.zeros(shape=(*gray.shape, 3))
# 2: 遍历每个像素点
for i in range(rgb_image.shape[0]):
for j in range(rgb_image.shape[1]):
# 3:对不同的灰度值选择不同的颜色
if gray[i, j] < 92:
rgb_image[i, j, :] = color_dict["green"]
elif gray[i, j] >= 92:
rgb_image[i, j, :] = color_dict["blue"]
return rgb_image.astype(np.uint8)
img_color = gray2rgb(img.astype(np.uint8), color_dict)
cv2.imshow("colored", img_color)
cv2.waitKey(0)
cv2.destroyAllWindows()