python - 收集所有不同轮廓的非零像素

标签 python opencv image-processing

我一直在尝试根据序列对轮廓进行排序(这里的序列无关紧要)。我有一个非常小的问题,那就是我应该在下面的代码段中传递的正确的numpy数组,我同时获得了正确的行/列(非零)像素。

row_pixels=cv2.countNonZero(blur[cy][:])

col_pixels=cv2.countNonZero(blur[:,cx])

我所做的结果如下:对于所有5个轮廓,我得到几乎相同数量的非零像素,我意识到这是因为我正在传递“整个”图像(如您在上方看到的那样,是整个图像),如下所示:用于计算像素的numpy数组是错误的,我意识到这一点。

当前输入:下图(无标记)

预期输出:对于所有5个轮廓,行/列(NonZero)像素。

我目前正在做的是:
import cv2
import numpy as np
from imutils import perspective
from imutils import contours 
import imutils 
from scipy.spatial import distance as dist
import argparse
import pandas as pd
import time

parser = argparse.ArgumentParser(description='Object Detection and Tracking using YOLO in OPENCV')
parser.add_argument('--image', help='Path to image file.')

args = parser.parse_args()
font=cv2.FONT_HERSHEY_SIMPLEX


start=time.time()
im_in = cv2.imread(args.image, 0)
_, thres2=cv2.threshold(im_in, 140, 255,cv2.THRESH_BINARY_INV)
dilate = cv2.dilate(thres2,None)
erode = cv2.erode(dilate,None)

im_3=erode.copy()

blur=cv2.medianBlur(im_3,5)

a=[]
r=[] 
row_col_pixel_values=[]
cl=[]
data=[]
global mainar
#find contours 
_,contour2,_=cv2.findContours(blur,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_NONE)
# print(contour2)
for c in contour2:
    area=cv2.contourArea(c)
    if area>10000 and area <30000:
        a.append(area)

        cv2.drawContours(blur, [c], 0, (128, 128, 128), 1)


        M=cv2.moments(c)
        cx=int((M["m10"]/M["m00"]))
        cy=int((M["m01"]/M["m00"]))
        center =(cx,cy)
        data.append((cx,cy))
        cv2.circle(blur,(cx,cy), 5,(128,128,128),-1)
        print("",cx,cy)
        print(len(blur[cy][:])) 
        # one=blur[c]
        row_pixels=cv2.countNonZero(blur[cy][:])

        col_pixels=cv2.countNonZero(blur[:,cx])
        comb=(row_pixels,col_pixels)
        cl.append(comb)

nparea=np.array(a)
npcentercoord=np.array(data)

row_col_pixel_values=np.array(cl)
print("Area of 5 contours :",nparea)
print("Center coordinates of 5 contours:",npcentercoord)

print("Row and Column pixel values of 5 contours:",row_col_pixel_values)

mainar=np.column_stack((nparea,npcentercoord,row_col_pixel_values))
# print(mainar)

mainar[:,[1]] = (mainar[:,[1]]).astype(int)

MinX = int(min([_[1] for _ in mainar]))
MinlowerX = (MinX - 10) 
MinupperX = (MinX + 10)
MinY = int(min([_[2] for _ in mainar]))
MinlowerY = (MinY - 10) 
MinupperY = (MinY + 10)
MaxX = int(max([_[1] for _ in mainar]))
MaxlowerX = (MaxX - 10) 
MaxupperX = (MaxX + 10)
MaxY = int(max([_[2] for _ in mainar]))
MaxlowerY = (MaxY - 10)
MaxupperY = (MaxY + 10)

print("", MinX,MinY,MaxX,MaxY)


def PixeltoNumeric(channel,rowMM,colMM):

    if channel=="4S":
        for i in range(0, len(mainar[:,1])):
            cx=mainar[i,1]
            cy=mainar[i,2]
            if (cx in range(MinlowerX,MinupperX+1)) and (cy in range(MinlowerY,MinupperY+1)):
                rowp=mainar[i,3]
                colp=mainar[i,4]
                print("The center coordinates(x,y) and (Row/Col) pixels of 4Schannel: ")
                print("1 pixel has {:.5f} many mm in row:".format(rowMM/rowp))
                print("1 pixel has {:.5f} many mm in col:".format(colMM/colp))
                print(cx,cy,rowp,colp)

    if channel == '1':
            for i in range(0, len(mainar[:,1])):
                cx=mainar[i,1]
                cy=mainar[i,2]
                if (cx in range(MaxlowerX,MaxupperX+1)) and (cy in range(MaxlowerY,MaxupperY+1)):
                    rowp=mainar[i,3]
                    colp=mainar[i,4]
                    print("The center coordinates(x,y) and (Row/Col) pixels of 1Channel: ")
                    print("1 pixel has {:.5f} many mm in row:".format(rowMM/rowp))
                    print("1 pixel has {:.5f} many mm in col:".format(colMM/colp))
                    print(cx,cy,rowp,colp)

    if channel == '2':
        for i in range(0, len(mainar[:,1])):
            cx=mainar[i,1]
            cy=mainar[i,2]
            if (cx in range(MinlowerX,MinupperX+1)) and (cy in range(MaxlowerY,MaxupperY+1)):
                rowp=mainar[i,3]
                colp=mainar[i,4]
                print("The center coordinates(x,y) and (Row/Col) pixels of 2Channel: ")
                print("1 pixel has {:.5f} many mm in row:".format(rowMM/rowp))
                print("1 pixel has {:.5f} many mm in col:".format(colMM/colp))
                print(cx,cy,rowp,colp)

    if channel == '3':
        for i in range(0, len(mainar[:,1])):
            cx=mainar[i,1]
            cy=mainar[i,2]
            if (cx in range(((MinlowerX+MaxlowerX)//2),((MinupperX+MaxupperX+1)//2)) and (cy in range(((MinlowerY+MaxlowerY)//2),((MinupperY+MaxupperY+1)//2)))):
                rowp=mainar[i,3]
                colp=mainar[i,4]
                print("The center coordinates(x,y) and (Row/Col) pixels of 3Channel: ")
                print("1 pixel has {:.5f} many mm in row:".format(rowMM/rowp))
                print("1 pixel has {:.5f} many mm in col:".format(colMM/colp))
                print(cx,cy,rowp,colp)

    if channel == '4N':
        for i in range(0, len(mainar[:,1])):
            cx=mainar[i,1]
            cy=mainar[i,2]
            if (cx in range(MaxlowerX,MaxupperX+1)) and (cy in range(MinlowerY,MinupperY+1)):
                rowp=mainar[i,3]
                colp=mainar[i,4]
                print("The center coordinates(x,y) and (Row/Col) pixels of 4NChannel: ")
                print("1 pixel has {:.5f} many mm in row:".format(rowMM/rowp))
                print("1 pixel has {:.5f} many mm in col:".format(colMM/colp))
                print(cx,cy,rowp,colp)

    return (cv2.imshow("4",blur))


cv2.waitKey(0)
cv2.destroyAllWindows()

Input Image
Expected Output(The number of pixels are wrong here)
Simple Illustration of the contours

最佳答案

我不确定我是否正确理解您,但我的理解是您想找到所有轮廓内像素的所有坐标(x,y)。如果这是您的问题,则可以使用以下代码实现:

import cv2
import matplotlib.pyplot as plt
import numpy as np

im_in = cv2.imread(r'image.png', 0)
_, thres2 = cv2.threshold(im_in, 140, 255, cv2.THRESH_BINARY_INV)
dilate = cv2.dilate(thres2, None)
erode = cv2.erode(dilate, None)
im_3 = erode.copy()
blur = cv2.medianBlur(im_3, 5)

# I am using OpenCV 4 therefore it returns only 4 parameters
contour2, _ = cv2.findContours(blur, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
extracted = np.zeros(blur.shape, np.uint8)

for c in contour2:
    area = cv2.contourArea(c)
    # I have modified these values to make it work for attached picture
    if 10000 < area < 300000: 
        cv2.drawContours(extracted, [c], 0, (255), cv2.FILLED)

contour_x, contour_y = np.nonzero(extracted)

plt.imshow(extracted, 'gray')
plt.show()

这是提取的image

更新1

经过您的解释,我了解到您想计算每个单独轮廓的宽度和高度。根据您提供的示例代码,我假设您想使用与轮廓中心交叉的线来测量宽度和高度。您可以通过在清晰的图像上绘制和测量轮廓来实现。请参见下面的代码:
# I am using OpenCV 4 therefore it returns only 4 parameters
contour2, _ = cv2.findContours(blur, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
extracted = np.zeros(blur.shape, np.uint8)
contoursSize = []
for c in contour2:
    area = cv2.contourArea(c)
    # I have modified these values to make it work for attached picture
    if 10000 < area < 300000:
        M = cv2.moments(c)
        cx = int((M["m10"] / M["m00"]))
        cy = int((M["m01"] / M["m00"]))
        extracted.fill(0) 
        cv2.drawContours(extracted, [c], 0, 255, cv2.FILLED)
        width = cv2.countNonZero(extracted[cy][:])
        height = cv2.countNonZero(extracted[:, cx])
        contoursSize.append((width, height))

关于python - 收集所有不同轮廓的非零像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57416442/

相关文章:

HTML 格式的 Python 电子邮件 mimelib

python - 稀疏向量 pyspark

c# - 如何检测图像中能量最低的区域

c# - 如何获取和设置 CMYK 格式的像素颜色?

opencv - 模板匹配?对象识别和特征匹配或解决方案是什么?

python - 将 bootstrap 或 sylilng 添加到内置表单的 django

python代码组织

python - 如何找到最大的轮廓?

c++将部分数组(在某个偏移量处)转换为不同的类型

opencv - SolvePnPRansac返回不同的结果