这是 Python/OpenCV/Skimage 中的一种方法
- Read the input
- Stretch to full dynamic range
- Apply morphology to clean the image
- Convert to gray
- Otsu threshold
- Get the largest contour
- Draw the contour outline on the stretched image
- Extract the contour region from the stretched image and place it on a black background
- Save the results
输入:
import cv2
import numpy as np
import skimage.exposure
# read image
img = cv2.imread('dark_image.png')
hh, ww = img.shape[:2]
# stretch dynamic range
stretch = skimage.exposure.rescale_intensity(img, in_range='image', out_range=(0,255))
# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (101,101))
morph = cv2.morphologyEx(stretch, cv2.MORPH_CLOSE, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel)
# convert to grayscale
gray = cv2.cvtColor(morph,cv2.COLOR_BGR2GRAY)
# threshold
#thresh = cv2.threshold(gray, 30, 255, cv2.THRESH_BINARY)[1]\
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# get largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
# draw contour on stretched image
result1 = stretch.copy()
cv2.drawContours(result1, [big_contour], 0, (255,255,255), 1)
# draw region on black background
contour = np.zeros((stretch.shape[:2]), dtype=np.uint8)
result2 = np.zeros_like(stretch)
cv2.drawContours(contour, [big_contour], 0, 255, -1)
result2[contour > 0] = stretch[contour > 0]
# save result
cv2.imwrite("dark_image_stretch.jpg", stretch)
cv2.imwrite("dark_image_morph.jpg", morph)
cv2.imwrite("dark_image_gray.jpg", gray)
cv2.imwrite("dark_image_threshold.jpg", thresh)
cv2.imwrite("dark_image_result1.jpg", result1)
cv2.imwrite("dark_image_result2.jpg", result2)
# view result
cv2.imshow("stretch", stretch)
cv2.imshow("morph", morph)
cv2.imshow("gray", gray)
cv2.imshow("threshold", thresh)
cv2.imshow("result1", result1)
cv2.imshow("result2", result2)
cv2.waitKey(0)
cv2.destroyAllWindows()
拉伸到全动态范围图像:
形态清洁图像:
灰色图像:
阈值图像:
拉伸图像上的轮廓轮廓:
黑色背景上拉伸图像的轮廓区域: