Python 有没有办法用OpenCV更好地加载图像
我想加载图像并使用hough变换捕获纸张内的黑色边界区域,然后在框内执行一些计数操作。当然,这要求我能够以相对良好的质量加载图像 问题是,当我使用openCV的cv2.imread()加载时,我得到了一个非常淡化的图片版本,我无法快速处理。更糟糕的是,我无法使用cv2.imshow()渲染图像,每次尝试查看时,我的IDE都会挂起。因此,我必须使用matplotlib一步一步地渲染和查看图像 我不知道还有其他的图像处理软件包(可能是枕头,但我不知道它是否能满足我的需要) 我的原始图像是: 因为cv2.imshow()方法导致窗口崩溃,所以我求助于matplotlib:Python 有没有办法用OpenCV更好地加载图像,python,image,opencv,image-processing,Python,Image,Opencv,Image Processing,我想加载图像并使用hough变换捕获纸张内的黑色边界区域,然后在框内执行一些计数操作。当然,这要求我能够以相对良好的质量加载图像 问题是,当我使用openCV的cv2.imread()加载时,我得到了一个非常淡化的图片版本,我无法快速处理。更糟糕的是,我无法使用cv2.imshow()渲染图像,每次尝试查看时,我的IDE都会挂起。因此,我必须使用matplotlib一步一步地渲染和查看图像 我不知道还有其他的图像处理软件包(可能是枕头,但我不知道它是否能满足我的需要) 我的原始图像是: 因为c
plt.imshow(img)
plt.title('my picture')
plt.show()
结果是:
之后:
gray = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 75, 150)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 50, 50, 5)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 5)
plt.imshow(img)
plt.title('my picture')
plt.show()
输出为:
正如你所看到的,非常混乱。我的直觉是,这是因为原始图像的加载方式。有什么方法可以改进加载过程,以便更容易地应用Hough线吗?我相信使用
cv2.imread()
可以很好地加载图像,但是由于图像太大,尺寸2976x3838
,您的IDE无法显示图像。我认为您应用的cv2.HoughLinesP()
不正确。这里不是使用cv2.HoughLinesP()
,而是一种检测行的替代方法
其思想是先设置阈值,然后找到电路板的边界框来创建遮罩。从这个遮罩中,我们执行透视变换以获得自上而下的图像。这将使我们能够更好地检测线条 一旦检测到电路板,我们就可以提取ROI 然后我们简单地检测垂直线和水平线 结果
import cv2
import numpy as np
def perspective_transform(image, corners):
def order_corner_points(corners):
# Separate corners into individual points
# Index 0 - top-right
# 1 - top-left
# 2 - bottom-left
# 3 - bottom-right
corners = [(corner[0][0], corner[0][1]) for corner in corners]
top_r, top_l, bottom_l, bottom_r = corners[0], corners[1], corners[2], corners[3]
return (top_l, top_r, bottom_r, bottom_l)
# Order points in clockwise order
ordered_corners = order_corner_points(corners)
top_l, top_r, bottom_r, bottom_l = ordered_corners
# Determine width of new image which is the max distance between
# (bottom right and bottom left) or (top right and top left) x-coordinates
width_A = np.sqrt(((bottom_r[0] - bottom_l[0]) ** 2) + ((bottom_r[1] - bottom_l[1]) ** 2))
width_B = np.sqrt(((top_r[0] - top_l[0]) ** 2) + ((top_r[1] - top_l[1]) ** 2))
width = max(int(width_A), int(width_B))
# Determine height of new image which is the max distance between
# (top right and bottom right) or (top left and bottom left) y-coordinates
height_A = np.sqrt(((top_r[0] - bottom_r[0]) ** 2) + ((top_r[1] - bottom_r[1]) ** 2))
height_B = np.sqrt(((top_l[0] - bottom_l[0]) ** 2) + ((top_l[1] - bottom_l[1]) ** 2))
height = max(int(height_A), int(height_B))
# Construct new points to obtain top-down view of image in
# top_r, top_l, bottom_l, bottom_r order
dimensions = np.array([[0, 0], [width - 1, 0], [width - 1, height - 1],
[0, height - 1]], dtype = "float32")
# Convert to Numpy format
ordered_corners = np.array(ordered_corners, dtype="float32")
# Find perspective transform matrix
matrix = cv2.getPerspectiveTransform(ordered_corners, dimensions)
# Return the transformed image
return cv2.warpPerspective(image, matrix, (width, height))
image = cv2.imread('1.jpg')
original = image.copy()
blur = cv2.bilateralFilter(image,9,75,75)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,0,255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
mask = np.zeros(image.shape, dtype=np.uint8)
for c in cnts:
area = cv2.contourArea(c)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.015 * peri, True)
if area > 150000 and len(approx) == 4:
cv2.drawContours(image,[c], 0, (36,255,12), 3)
cv2.drawContours(mask,[c], 0, (255,255,255), -1)
transformed = perspective_transform(original, approx)
mask = cv2.bitwise_and(mask, original)
# Remove horizontal lines
gray = cv2.cvtColor(transformed, cv2.COLOR_BGR2GRAY)
board_thresh = cv2.threshold(gray,0,255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)[1]
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (55,1))
detect_horizontal = cv2.morphologyEx(board_thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(transformed, [c], -1, (36,255,12), 9)
pass
# Remove vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,55))
detect_vertical = cv2.morphologyEx(board_thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(transformed, [c], -1, (36,255,12), 9)
cv2.imwrite('thresh.png', thresh)
cv2.imwrite('image.png', image)
cv2.imwrite('mask.png', mask)
cv2.imwrite('transformed.png', transformed)
cv2.waitKey()
我相信使用
cv2.imread()
可以很好地加载图像,但是它太大了,尺寸2976x3838
,您的IDE无法显示图像。我认为您应用的cv2.HoughLinesP()
不正确。这里不是使用cv2.HoughLinesP()
,而是一种检测行的替代方法
其思想是先设置阈值,然后找到电路板的边界框来创建遮罩。从这个遮罩中,我们执行透视变换以获得自上而下的图像。这将使我们能够更好地检测线条 一旦检测到电路板,我们就可以提取ROI 然后我们简单地检测垂直线和水平线 结果
import cv2
import numpy as np
def perspective_transform(image, corners):
def order_corner_points(corners):
# Separate corners into individual points
# Index 0 - top-right
# 1 - top-left
# 2 - bottom-left
# 3 - bottom-right
corners = [(corner[0][0], corner[0][1]) for corner in corners]
top_r, top_l, bottom_l, bottom_r = corners[0], corners[1], corners[2], corners[3]
return (top_l, top_r, bottom_r, bottom_l)
# Order points in clockwise order
ordered_corners = order_corner_points(corners)
top_l, top_r, bottom_r, bottom_l = ordered_corners
# Determine width of new image which is the max distance between
# (bottom right and bottom left) or (top right and top left) x-coordinates
width_A = np.sqrt(((bottom_r[0] - bottom_l[0]) ** 2) + ((bottom_r[1] - bottom_l[1]) ** 2))
width_B = np.sqrt(((top_r[0] - top_l[0]) ** 2) + ((top_r[1] - top_l[1]) ** 2))
width = max(int(width_A), int(width_B))
# Determine height of new image which is the max distance between
# (top right and bottom right) or (top left and bottom left) y-coordinates
height_A = np.sqrt(((top_r[0] - bottom_r[0]) ** 2) + ((top_r[1] - bottom_r[1]) ** 2))
height_B = np.sqrt(((top_l[0] - bottom_l[0]) ** 2) + ((top_l[1] - bottom_l[1]) ** 2))
height = max(int(height_A), int(height_B))
# Construct new points to obtain top-down view of image in
# top_r, top_l, bottom_l, bottom_r order
dimensions = np.array([[0, 0], [width - 1, 0], [width - 1, height - 1],
[0, height - 1]], dtype = "float32")
# Convert to Numpy format
ordered_corners = np.array(ordered_corners, dtype="float32")
# Find perspective transform matrix
matrix = cv2.getPerspectiveTransform(ordered_corners, dimensions)
# Return the transformed image
return cv2.warpPerspective(image, matrix, (width, height))
image = cv2.imread('1.jpg')
original = image.copy()
blur = cv2.bilateralFilter(image,9,75,75)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,0,255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
mask = np.zeros(image.shape, dtype=np.uint8)
for c in cnts:
area = cv2.contourArea(c)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.015 * peri, True)
if area > 150000 and len(approx) == 4:
cv2.drawContours(image,[c], 0, (36,255,12), 3)
cv2.drawContours(mask,[c], 0, (255,255,255), -1)
transformed = perspective_transform(original, approx)
mask = cv2.bitwise_and(mask, original)
# Remove horizontal lines
gray = cv2.cvtColor(transformed, cv2.COLOR_BGR2GRAY)
board_thresh = cv2.threshold(gray,0,255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)[1]
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (55,1))
detect_horizontal = cv2.morphologyEx(board_thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(transformed, [c], -1, (36,255,12), 9)
pass
# Remove vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,55))
detect_vertical = cv2.morphologyEx(board_thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(transformed, [c], -1, (36,255,12), 9)
cv2.imwrite('thresh.png', thresh)
cv2.imwrite('image.png', image)
cv2.imwrite('mask.png', mask)
cv2.imwrite('transformed.png', transformed)
cv2.waitKey()
很可能你的图像加载得很好,只是当你显示它时,你不能显示所有的像素。试着在显示器上显示一个足够小的图像区域,看看你得到了什么。即使在专业编写软件近20年后,我的直觉是问题出在我的代码上,而不是(广泛使用的)第三方库。事实并非如此,这相当罕见只需将图像重新写入另一个文件,即可确认
imread
工作正常。考虑到输入的大小,最好还是将结果保存到文件中,并使用适当的图像视图来显示和检查它。在这里以小于10%的比例绘制它将不允许您看到任何相关内容。实际上,在我看来,您对cv2.HoughLinesP
的调用是不正确的——第五个参数是lines
,所以主要问题是您实际上告诉它查找至少5像素长的线。。。当图像的宽度约为2500像素时。很可能你的图像加载得很好,只是当你显示它时,你不能显示所有的像素。试着在显示器上显示一个足够小的图像区域,看看你得到了什么。即使在专业编写软件近20年后,我的直觉是问题出在我的代码上,而不是(广泛使用的)第三方库。事实并非如此,这相当罕见只需将图像重新写入另一个文件,即可确认imread
工作正常。考虑到输入的大小,最好还是将结果保存到文件中,并使用适当的图像视图来显示和检查它。在这里以小于10%的比例绘制它将不允许您看到任何相关内容。实际上,在我看来,您对cv2.HoughLinesP
的调用是不正确的——第五个参数是lines
,所以主要问题是您实际上告诉它查找至少5像素长的线。。。当图像的宽度约为2500像素时。你真是个天才。剧本很有魅力。但是,如果我将其当前形式与一起使用,输出将向右旋转90度。你知道为什么会发生这种情况吗?@Sam,它之所以转90度是因为顺时针方向获得了四个角点。您只需使用cv2.rotate()
或获取正确的orientation@nathancy你是个天才。剧本很有魅力。但是,如果我将其当前形式与一起使用,输出将向右旋转90度。你知道为什么会发生这种情况吗?@Sam,它之所以转90度是因为顺时针方向获得了四个角点。您可以简单地使用cv2.rotate()
或获得正确的方向