我需要使用python OpenCV从这个矩形框中提取图像。
我看过并尝试过几种从形状内部提取内容的方法,但每种方法都有局限性。(0,255,0)或红色(255,0,0)。然而,我的问题是红框有一些透明/不透明,使矩形的识别困难得多。矩形的红色像素颜色范围从175- 220,但是图像的其余部分也具有类似的红色色调,使得提取更加困难。
我对OpenCV还是个新手,所以非常感谢您的帮助。我已经在this线程上尝试了这两种解决方案,但是都没有产生预期的结果。
pqwbnv8z1#
以下是一个可能的解决方案:1.将图像转换为HSV1.红色阈值用于分割矩形1.应用一些形态学以尽可能闭合轮廓1.检测外部轮廓1.根据面积过滤噪声斑点;您正在寻找最大的轮廓1.获取轮廓的边界矩形1.切片使用边界矩形的图像让我们看看代码:
HSV
# 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)
这就是结果:
矩形稍大一些,但噪声也大一些。但是,我们要寻找最大的斑点,所以我们可以按面积过滤。让我们裁剪最大的斑点:
# 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)
现在,因为我们正在处理一个变形图像,矩形二进制轮廓比实际的红色矩形稍大,所以我引入了一个偏移量,以更紧密地裁剪图像。这是偏移量为15像素的边框:
15
这是裁剪后的图像:
4smxwvx52#
非常感谢你的帮助;这是非常有帮助的!我确实必须修改代码,以概括它足以适用于数百万张图像。我得到了大约95%+的准确率。错误包括图像中的多个建筑物非常接近红色屋顶,深红色土壤,车辆...基本上任何红色的东西。因此,我把最小面积的阈值提高到一个很高的值,以排除红色框外的大的红色物体。希望这对其他人有帮助。主要变更...1.我删除了偏移,它没有概括得足够好,在一些图像中,所需的内容被从最终产品中剪掉了。1.我确实需要合并轮廓以避免出现大量较小的矩形,这也是我增加minArea阈值的原因。我发现即使是100的小减量有时也会产生2+轮廓,所以我必须在计算边界矩形之前将它们合并。1.非常重要的是,我创建了一个上限和下限颜色范围,以确保我得到的是红色框所涵盖的整个区域。由于红色框的透明度,色调和饱和度无处不在,这有助于始终确保我捕捉到所需的内容。希望这对其他人有帮助。
# 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 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 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 offset = 15 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.非常重要的是,我创建了一个上限和下限颜色范围,以确保我得到的是红色框所涵盖的整个区域。由于红色框的透明度,色调和饱和度无处不在,这有助于始终确保我捕捉到所需的内容。
希望这对其他人有帮助。