我需要使用python OpenCV从这个矩形框中提取图像。
我看过并尝试过几种从形状内部提取内容的方法,但每种方法都有局限性。(0,255,0)或红色(255,0,0)。然而,我的问题是红框有一些透明/不透明,使矩形的识别困难得多。矩形的红色像素颜色范围从175- 220,但是图像的其余部分也具有类似的红色色调,使得提取更加困难。
我对OpenCV还是个新手,所以非常感谢您的帮助。我已经在this线程上尝试了这两种解决方案,但是都没有产生预期的结果。
pqwbnv8z1#
以下是一个可能的解决方案:1.将图像转换为HSV1.红色阈值用于分割矩形1.应用一些形态学以尽可能闭合轮廓1.检测外部轮廓1.根据面积过滤噪声斑点;您正在寻找最大的轮廓1.获取轮廓的边界矩形1.切片使用边界矩形的图像让我们看看代码:
HSV
# imports:import cv2import numpy as np# image pathpath = "D://opencvImages//"fileName = "uHNzL.jpg"# Reading an image in default mode:inputImage = cv2.imread(path + fileName)# Deep copy for results:inputImageCopy = inputImage.copy()# Convert the image to the HSV color space:hsvImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2HSV)# Set the HSV values:lowRange = np.array([144, 105, 0])uppRange = np.array([179, 255, 255])# Create the HSV maskbinaryMask = cv2.inRange(hsvImage, lowRange, uppRange)
# imports:
import cv2
import numpy as np
# image path
path = "D://opencvImages//"
fileName = "uHNzL.jpg"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Deep copy for results:
inputImageCopy = inputImage.copy()
# Convert the image to the HSV color space:
hsvImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2HSV)
# Set the HSV values:
lowRange = np.array([144, 105, 0])
uppRange = np.array([179, 255, 255])
# Create the HSV mask
binaryMask = cv2.inRange(hsvImage, lowRange, uppRange)
这是面具:
正如你所看到的,矩形(大部分)在那里。让我们尝试用一些形态学来改善轮廓。一些扩张和侵 eclipse 应该可以做到这一点:
# Apply Dilate + Erode:kernel = np.ones((3, 3), np.uint8)binaryMask = cv2.morphologyEx(binaryMask, cv2.MORPH_DILATE, kernel, iterations=3)binaryMask = cv2.morphologyEx(binaryMask, cv2.MORPH_ERODE, kernel, iterations=3)
# Apply Dilate + Erode:
kernel = np.ones((3, 3), np.uint8)
binaryMask = cv2.morphologyEx(binaryMask, cv2.MORPH_DILATE, kernel, iterations=3)
binaryMask = cv2.morphologyEx(binaryMask, cv2.MORPH_ERODE, kernel, iterations=3)
这就是结果:
矩形稍大一些,但噪声也大一些。但是,我们要寻找最大的斑点,所以我们可以按面积过滤。让我们裁剪最大的斑点:
# Find the target blobs on the binary mask:contours, hierarchy = cv2.findContours(binaryMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# Alright, just look for the outer bounding boxes:for _, c in enumerate(contours): # Get blob area: blobArea = cv2.contourArea(c) # Set minimum area: minArea = 1000 if blobArea > minArea: # Get the bounding rectangle: boundRect = cv2.boundingRect(c) # Bondary offset: offset = 15 # Draw the rectangle on the input image: # Get the dimensions of the bounding rect: rectX = int(boundRect[0] + offset) rectY = int(boundRect[1] + offset) rectWidth = int(boundRect[2] - 2 * offset) rectHeight = int(boundRect[3] - 2 * offset) # Green Color, detected blobs: color = (0, 255, 0) cv2.rectangle(inputImageCopy, (int(rectX), int(rectY)), (int(rectX + rectWidth), int(rectY + rectHeight)), color, 2) # Crop contour: croppedImage = inputImage[rectY:rectY + rectHeight, rectX:rectX + rectWidth] cv2.imshow("croppedImage", croppedImage) cv2.waitKey(0) cv2.imshow("Rectangles", inputImageCopy) cv2.waitKey(0)
# Find the target blobs on the binary mask:
contours, hierarchy = cv2.findContours(binaryMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Alright, just look for the outer bounding boxes:
for _, c in enumerate(contours):
# Get blob area:
blobArea = cv2.contourArea(c)
# Set minimum area:
minArea = 1000
if blobArea > minArea:
# Get the bounding rectangle:
boundRect = cv2.boundingRect(c)
# Bondary offset:
offset = 15
# Draw the rectangle on the input image:
# Get the dimensions of the bounding rect:
rectX = int(boundRect[0] + offset)
rectY = int(boundRect[1] + offset)
rectWidth = int(boundRect[2] - 2 * offset)
rectHeight = int(boundRect[3] - 2 * offset)
# Green Color, detected blobs:
color = (0, 255, 0)
cv2.rectangle(inputImageCopy, (int(rectX), int(rectY)),
(int(rectX + rectWidth), int(rectY + rectHeight)), color, 2)
# Crop contour:
croppedImage = inputImage[rectY:rectY + rectHeight, rectX:rectX + rectWidth]
cv2.imshow("croppedImage", croppedImage)
cv2.waitKey(0)
cv2.imshow("Rectangles", inputImageCopy)
现在,因为我们正在处理一个变形图像,矩形二进制轮廓比实际的红色矩形稍大,所以我引入了一个偏移量,以更紧密地裁剪图像。这是偏移量为15像素的边框:
15
这是裁剪后的图像:
4smxwvx52#
非常感谢你的帮助;这是非常有帮助的!我确实必须修改代码,以概括它足以适用于数百万张图像。我得到了大约95%+的准确率。错误包括图像中的多个建筑物非常接近红色屋顶,深红色土壤,车辆...基本上任何红色的东西。因此,我把最小面积的阈值提高到一个很高的值,以排除红色框外的大的红色物体。希望这对其他人有帮助。主要变更...1.我删除了偏移,它没有概括得足够好,在一些图像中,所需的内容被从最终产品中剪掉了。1.我确实需要合并轮廓以避免出现大量较小的矩形,这也是我增加minArea阈值的原因。我发现即使是100的小减量有时也会产生2+轮廓,所以我必须在计算边界矩形之前将它们合并。1.非常重要的是,我创建了一个上限和下限颜色范围,以确保我得到的是红色框所涵盖的整个区域。由于红色框的透明度,色调和饱和度无处不在,这有助于始终确保我捕捉到所需的内容。希望这对其他人有帮助。
# Original imagesrc = cv2.imread(img_file, cv2.IMREAD_COLOR)img = cv2.cvtColor(src, cv2.COLOR_BGR2RGB )# HSVhsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)# lower boundary RED color range values; Hue (0 - 10)lower1 = np.array([0, 100, 20])upper1 = np.array([10, 255, 255]) # upper boundary RED color range values; Hue (160 - 180)lower2 = np.array([160,100,20])upper2 = np.array([179,255,255]) lower_mask = cv2.inRange(hsv, lower1, upper1)upper_mask = cv2.inRange(hsv, lower2, upper2) binaryMask = lower_mask + upper_mask# kernel dialation and erodekernel = np.ones((3, 3), np.uint8)binaryMask = cv2.morphologyEx(binaryMask, cv2.MORPH_DILATE, kernel, iterations=3)binaryMask = cv2.morphologyEx(binaryMask, cv2.MORPH_ERODE, kernel, iterations=3)# Find the target blobcontours, hierarchy = cv2.findContours(binaryMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)flag = TrueminArea = 50_000while flag and minArea > 100: contours_ = [contour for contour in contours if cv2.contourArea(contour) > minArea] contoursAreas = [cv2.contourArea(contour) for contour in contours] if contours_: contour = np.vstack(contours_) flag = False else: minArea -= 500# blob to bounding rectangleoffset = 15boundRect = cv2.boundingRect(contour)rectX = int(boundRect[0])rectY = int(boundRect[1])rectWidth = int(boundRect[2])rectHeight = int(boundRect[3])# Crop orignal image and save imagecroppedImage = src[rectY:rectY + rectHeight, rectX:rectX + rectWidth]imgFName = os.path.split(img_file)[-1]imgFPath = os.path.join(OUT_IMG_PATH, imgFName)cv2.imwrite(imgFPath, croppedImage)
# Original image
src = cv2.imread(img_file, cv2.IMREAD_COLOR)
img = cv2.cvtColor(src, cv2.COLOR_BGR2RGB )
# HSV
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
# lower boundary RED color range values; Hue (0 - 10)
lower1 = np.array([0, 100, 20])
upper1 = np.array([10, 255, 255])
# upper boundary RED color range values; Hue (160 - 180)
lower2 = np.array([160,100,20])
upper2 = np.array([179,255,255])
lower_mask = cv2.inRange(hsv, lower1, upper1)
upper_mask = cv2.inRange(hsv, lower2, upper2)
binaryMask = lower_mask + upper_mask
# kernel dialation and erode
# Find the target blob
contours, hierarchy = cv2.findContours(binaryMask, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
flag = True
minArea = 50_000
while flag and minArea > 100:
contours_ = [contour for contour in contours
if cv2.contourArea(contour) > minArea]
contoursAreas = [cv2.contourArea(contour) for contour in contours]
if contours_:
contour = np.vstack(contours_)
flag = False
else:
minArea -= 500
# blob to bounding rectangle
boundRect = cv2.boundingRect(contour)
rectX = int(boundRect[0])
rectY = int(boundRect[1])
rectWidth = int(boundRect[2])
rectHeight = int(boundRect[3])
# Crop orignal image and save image
croppedImage = src[rectY:rectY + rectHeight, rectX:rectX + rectWidth]
imgFName = os.path.split(img_file)[-1]
imgFPath = os.path.join(OUT_IMG_PATH, imgFName)
cv2.imwrite(imgFPath, croppedImage)
2条答案
按热度按时间pqwbnv8z1#
以下是一个可能的解决方案:
1.将图像转换为
HSV
1.红色阈值用于分割矩形
1.应用一些形态学以尽可能闭合轮廓
1.检测外部轮廓
1.根据面积过滤噪声斑点;您正在寻找最大的轮廓
1.获取轮廓的边界矩形
1.切片使用边界矩形的图像
让我们看看代码:
这是面具:
正如你所看到的,矩形(大部分)在那里。让我们尝试用一些形态学来改善轮廓。一些扩张和侵 eclipse 应该可以做到这一点:
这就是结果:
矩形稍大一些,但噪声也大一些。但是,我们要寻找最大的斑点,所以我们可以按面积过滤。让我们裁剪最大的斑点:
现在,因为我们正在处理一个变形图像,矩形二进制轮廓比实际的红色矩形稍大,所以我引入了一个偏移量,以更紧密地裁剪图像。
这是偏移量为
15
像素的边框:这是裁剪后的图像:
4smxwvx52#
非常感谢你的帮助;这是非常有帮助的!我确实必须修改代码,以概括它足以适用于数百万张图像。我得到了大约95%+的准确率。错误包括图像中的多个建筑物非常接近红色屋顶,深红色土壤,车辆...基本上任何红色的东西。因此,我把最小面积的阈值提高到一个很高的值,以排除红色框外的大的红色物体。希望这对其他人有帮助。
主要变更...
1.我删除了偏移,它没有概括得足够好,在一些图像中,所需的内容被从最终产品中剪掉了。
1.我确实需要合并轮廓以避免出现大量较小的矩形,这也是我增加minArea阈值的原因。我发现即使是100的小减量有时也会产生2+轮廓,所以我必须在计算边界矩形之前将它们合并。
1.非常重要的是,我创建了一个上限和下限颜色范围,以确保我得到的是红色框所涵盖的整个区域。由于红色框的透明度,色调和饱和度无处不在,这有助于始终确保我捕捉到所需的内容。
希望这对其他人有帮助。