OpenCV中哪种像素计数方法对彩色图像更准确?

时间:2019-02-28 01:48:06

标签: c++ opencv image-processing colors

我有一个示例图片:

Source image

并且我使用不同的阈值方法来计算像素数。

第一种方法是简单的阈值处理,因为在源图像上我只有一个白色背景上的彩色对象。

    Mat image = imread("/$image_path", IMREAD_GRAYSCALE);
    Mat binary_image;
    threshold(image, binary_image, 120, 255, THRESH_BINARY);
    int TotalNumberOfPixels = binary_image.rows * binary_image.cols;
    int PixelCount = TotalNumberOfPixels - cv::countNonZero(binary_image);
    return PixelCount;

第二种方法是假设我的图像带有多个彩色对象(即多个彩色标记),因此我需要过滤并应用红色蒙版。我是通过以下方式完成的:

Mat image2 = imread("/$image_path", IMREAD_COLOR);
Mat blurred, edge;
Mat bgrInv = ~image2;
Mat hsvIm;
Mat maskRed;    

cvtColor(bgrInv, hsvIm, COLOR_BGR2HSV);

inRange(hsvIm, Scalar(80, 70, 239), Scalar(100, 255, 255), maskRed);
imshow("Mask", maskRed);

//blur(maskRed, blurred, Size(3, 3));
//Canny(blurred, edge, 75, 200, 3);

cout << "Pixel Count: " << countNonZero(maskRed)<< endl;

两种方法的输出为:

Method 1: 406
Method 2: 155

我将对彩色图像进行操作,因此我一开始使用的是第二种方法。但我不知道它是否“准确”或正确。

Here是我正在研究的示例模板。它基本上是带有较小色块的调查类型模板。用红色圆圈作为标记占位符,以便于进行前/后处理。

2 个答案:

答案 0 :(得分:0)

让我们看一下两种方法的输出。

这是方法1的binary_image

enter image description here

您要数-很麻烦(这是正确的英语吗?)-黑色像素,这与您计算红色像素的任务相对应。 (顺便说一句,将threshold颠倒过来,只计算白色像素。)

这是方法2的edge

enter image description here

您计算了白色像素,但是正如您所看到的,这只是初始红色对象的轮廓。这不符合您的原始任务。

因此,就这两种方法而言,就目前而言,对于给定的示例,第一种方法更加“准确”。但是,您提到了不同颜色的对象,因此应该重新设计方法2以计算适当的像素。

您能举例说明带有多个不同颜色物体的图像吗?

我还编辑了您的问题。 (尚未编辑修改。)图像加载部分很重要,因为我猜想,在方法1中,您在方法2中使用了imread(..., IMREAD_GRAYSCALE)imread(..., IMREAD_COLOR)

答案 1 :(得分:0)

我认为,如果图像模糊(例如JPEG格式),所有方法都不正确。但是,让我们假设它很清楚。

要计算彩色对象像素,我们可以计算全部colored pixels或全部RED pixels

(1)在colored中找到HSV个区域: How to detect colored patches in an image using OpenCV?

# count colored pixels in S(HSV)
def countColored(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h,s,v = cv2.split(hsv)
    num = np.sum(s>20)
    return num

(2)找到Red个区域: How to find the RED color regions using OpenCV?

def countRed(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h,s,v = cv2.split(hsv)
    mask1 = cv2.inRange(hsv, (0,50,20), (5,255,255))
    mask2 = cv2.inRange(hsv, (175,50,20), (180,255,255))
    mask = cv2.bitwise_or(mask1, mask2 )
    num = cv2.countNonZero(mask)
    return num

#!/usr/bin/python3
# 2019/02/28
import cv2
import numpy as np

def cvshow(img):
    cv2.imshow("OpenCV", img)
    cv2.waitKey();cv2.destroyAllWindows()

def countColored(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h,s,v = cv2.split(hsv)
    num = np.sum(s>20)
    return num

def countRed(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h,s,v = cv2.split(hsv)
    mask1 = cv2.inRange(hsv, (0,50,20), (5,255,255))
    mask2 = cv2.inRange(hsv, (175,50,20), (180,255,255))
    mask = cv2.bitwise_or(mask1, mask2 )
    num = cv2.countNonZero(mask)
    return num

if __name__ == "__main__":
    fpath = "fQipc.jpg"
    img = cv2.imread(fpath)
    num1 = countColored(img)
    num2 = countRed(img)
    print(num1, num2)
    # 643, 555