Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将单个等高线点拆分为';s HSV通道以执行附加操作_C++_Opencv - Fatal编程技术网

C++ 将单个等高线点拆分为';s HSV通道以执行附加操作

C++ 将单个等高线点拆分为';s HSV通道以执行附加操作,c++,opencv,C++,Opencv,我目前正在考虑计算等高线中点的平均HSV。我做了一些研究,发现了split函数,它允许将图像的一个矩阵分解到它的通道中,但是轮廓数据类型是一个点向量。下面是一个代码示例 findcontours(detected_edges,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE); vector<vector<Point>> ContourHsvChannels(3); split(contours,ContourHsvChan

我目前正在考虑计算等高线中点的平均HSV。我做了一些研究,发现了split函数,它允许将图像的一个矩阵分解到它的通道中,但是轮廓数据类型是一个点向量。下面是一个代码示例

findcontours(detected_edges,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);    
vector<vector<Point>> ContourHsvChannels(3);
split(contours,ContourHsvChannels);
findcontours(检测到的边、轮廓、CV\u RETR\u列表、CV\u链\u近似\u简单);
矢量等高波通道(3);
分割(等高线、等高线/通道);

基本上,目标是将轮廓的每个点分割为其HSV通道,以便我可以对其执行操作。任何指导都将不胜感激。

您只需将轮廓绘制到与原始图像大小相同的空白图像上即可创建遮罩,然后使用该遮罩遮罩图像(HSV或任何您想要的颜色空间)。该函数接受一个
掩码
参数,以便您只获得掩码高亮显示的值的平均值

如果还需要标准偏差,可以使用该函数,它还接受一个
掩码

下面是Python中的一个示例:

import cv2
import numpy as np

# read image, ensure binary
img = cv2.imread('fg.png', 0)
img[img>0] = 255

# find contours in the image
contours = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)[1]

# create an array of blank images to draw contours on
n_contours = len(contours)
contour_imgs = [np.zeros_like(img) for i in range(n_contours)]

# draw each contour on a new image
for i in range(n_contours):
    cv2.drawContours(contour_imgs[i], contours, i, 255)

# color image of where the HSV values are coming from
color_img = cv2.imread('image.png')
hsv = cv2.cvtColor(color_img, cv2.COLOR_BGR2HSV)

# find the means and standard deviations of the HSV values for each contour
means = []
stddevs = []
for cnt_img in contour_imgs:
    mean, stddev = cv2.meanStdDev(hsv, mask=cnt_img)
    means.append(mean)
    stddevs.append(stddev)

print('First mean:')
print(means[0])
print('First stddev:')
print(stddevs[0])
第一个平均值:
[[146.3908046]
[51.2183908]
[202.95402299]]

第一个STDEV:
[[7.92835204]
[11.78682811]
[9.6154943]]

有三个价值观;每个频道一个


另一种选择是只查找所有值;轮廓是一个点数组,因此您可以使用轮廓数组中每个轮廓的这些点对图像进行索引,并将它们存储在单独的数组中,然后在这些点上找到
meanstdev()
mean()
(不必担心遮罩)。例如(同样在Python中,对此表示抱歉):

第一个平均值:
[[146.3908046]
[51.2183908]
[202.95402299]]

第一个STDEV:
[[7.92835204]
[11.78682811]
[9.6154943]]

所以这给出了相同的值。在Python中,我只是简单地创建了均值和标准差的空白列表,并将其添加到列表中。在C++中,你可以创建一个<代码> STD::vector < /代码>(假设代码> UTI88/COD>图像,否则,代码为> VEC3F或任何适当的)。然后在循环中,我创建另一个空白列表来保存每个轮廓的颜色;同样,这将是一个
std::vector
,然后在每个循环中对该向量运行
meanstdev()
,并将值附加到均值和标准偏差向量。您不必附加,您可以轻松获取轮廓的数量和每个轮廓中的点的数量,并预先分配速度,然后只索引到这些向量中,而不是附加


在Python中,两种方法之间几乎没有速度差异。当然,在第二个例子中有更好的内存效率;我们不存储整个空白的
Mat
,而是存储一些值。然而,后端OpenCV方法很快就可以用于掩蔽操作,所以你必须在C++中测试速度差,看看哪种方法更好。随着等高线数量的增加,我想第二种方法的好处也会增加。如果您同时使用这两种方法,请让我们知道您的结果

您只需在与原始图像大小相同的空白图像上绘制轮廓即可创建遮罩,然后使用该遮罩遮罩您的图像(HSV或任何您想要的颜色空间)。该函数接受一个
掩码
参数,以便您只获得掩码高亮显示的值的平均值

如果还需要标准偏差,可以使用该函数,它还接受一个
掩码

下面是Python中的一个示例:

import cv2
import numpy as np

# read image, ensure binary
img = cv2.imread('fg.png', 0)
img[img>0] = 255

# find contours in the image
contours = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)[1]

# create an array of blank images to draw contours on
n_contours = len(contours)
contour_imgs = [np.zeros_like(img) for i in range(n_contours)]

# draw each contour on a new image
for i in range(n_contours):
    cv2.drawContours(contour_imgs[i], contours, i, 255)

# color image of where the HSV values are coming from
color_img = cv2.imread('image.png')
hsv = cv2.cvtColor(color_img, cv2.COLOR_BGR2HSV)

# find the means and standard deviations of the HSV values for each contour
means = []
stddevs = []
for cnt_img in contour_imgs:
    mean, stddev = cv2.meanStdDev(hsv, mask=cnt_img)
    means.append(mean)
    stddevs.append(stddev)

print('First mean:')
print(means[0])
print('First stddev:')
print(stddevs[0])
第一个平均值:
[[146.3908046]
[51.2183908]
[202.95402299]]

第一个STDEV:
[[7.92835204]
[11.78682811]
[9.6154943]]

有三个价值观;每个频道一个


另一种选择是只查找所有值;轮廓是一个点数组,因此您可以使用轮廓数组中每个轮廓的这些点对图像进行索引,并将它们存储在单独的数组中,然后在这些点上找到
meanstdev()
mean()
(不必担心遮罩)。例如(同样在Python中,对此表示抱歉):

第一个平均值:
[[146.3908046]
[51.2183908]
[202.95402299]]

第一个STDEV:
[[7.92835204]
[11.78682811]
[9.6154943]]

所以这给出了相同的值。在Python中,我只是简单地创建了均值和标准差的空白列表,并将其添加到列表中。在C++中,你可以创建一个<代码> STD::vector < /代码>(假设代码> UTI88/COD>图像,否则,代码为> VEC3F或任何适当的)。然后在循环中,我创建另一个空白列表来保存每个轮廓的颜色;同样,这将是一个
std::vector
,然后在每个循环中对该向量运行
meanstdev()
,并将值附加到均值和标准偏差向量。您不必附加,您可以轻松获取轮廓的数量和每个轮廓中的点的数量,并预先分配速度,然后只索引到这些向量中,而不是附加


在Python中,两种方法之间几乎没有速度差异。当然,在第二个例子中有更好的内存效率;我们不存储整个空白的
Mat
,而是存储一些值。然而,后端OpenCV方法很快就可以用于掩蔽操作,所以你必须在C++中测试速度差,看看哪种方法更好。随着等高线数量的增加,我想第二种方法的好处也会增加。如果您同时使用这两种方法,请让我们知道您的结果

这是用c编写的解决方案++

#include <opencv2\opencv.hpp>
#include <iostream>
#include <vector>
#include <cmath>


using namespace cv;
using namespace std;

int main(int argc, char** argv) {


// Mat Declarations
// Mat img = imread("white.jpg");
// Mat src = imread("Rainbro.png");
Mat src = imread("multi.jpg");
// Mat src = imread("DarkRed.png");
Mat Hist;
Mat HSV;
Mat Edges;
Mat Grey;

vector<vector<Vec3b>> hueMEAN;
vector<vector<Point>> contours;

// Variables
int edgeThreshold = 1;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
int lowThreshold = 0;

// Windows
namedWindow("img", WINDOW_NORMAL);
namedWindow("HSV", WINDOW_AUTOSIZE);
namedWindow("Edges", WINDOW_AUTOSIZE);
namedWindow("contours", WINDOW_AUTOSIZE);

// Color Transforms
cvtColor(src, HSV, CV_BGR2HSV);
cvtColor(src, Grey, CV_BGR2GRAY);
// Perform Hist Equalization to help equalize Red hues so they stand out for 
// better Edge Detection

equalizeHist(Grey, Grey);


// Image Transforms
blur(Grey, Edges, Size(3, 3));
Canny(Edges, Edges, max_lowThreshold, lowThreshold * ratio, kernel_size);
findContours(Edges, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

//Rainbro MAT
//Mat drawing = Mat::zeros(432, 700, CV_8UC1);

//Multi MAT
Mat drawing = Mat::zeros(630, 1200, CV_8UC1);

//Red variation Mat
//Mat drawing = Mat::zeros(600, 900, CV_8UC1);

vector <vector<Point>> ContourPoints;

/* This code for loops through all contours and assigns the value of the y coordinate as a parameter
for the row pointer in the HSV mat. The value vec3b pointer pointing to the pixel in the mat is accessed
and stored for any Hue value that is between 0-10 and 165-179 as Red only contours.*/

for (int i = 0; i < contours.size(); i++) {
    vector<Vec3b> vf;
    vector<Point> points;
    bool isContourRed = false;

    for (int j = 0; j < contours[i].size(); j++) {
        //Row Y-Coordinate of Mat from Y-Coordinate of Contour
        int MatRow = int(contours[i][j].y);
        //Row X-Coordinate of Mat from X-Coordinate of Contour
        int MatCol = int(contours[i][j].x);

        Vec3b *HsvRow = HSV.ptr <Vec3b>(MatRow);

        int h = int(HsvRow[int(MatCol)][0]);
        int s = int(HsvRow[int(MatCol)][1]);
        int v = int(HsvRow[int(MatCol)][2]);

        cout << "Coordinate: ";
        cout << contours[i][j].x;
        cout << ",";
        cout << contours[i][j].y << endl;
        cout << "Hue: " << h << endl;

        // Get contours that are only in the red spectrum Hue 0-10, 165-179
        if ((h <= 10 || h >= 165 && h <= 180) && ((s > 0) && (v > 0))) {
            cout << "Coordinate: ";
            cout << contours[i][j].x;
            cout << ",";
            cout << contours[i][j].y << endl;
            cout << "Hue: " << h << endl;

            vf.push_back(Vec3b(h, s, v));
            points.push_back(contours[i][j]);
            isContourRed = true;
        }

    }
    if (isContourRed == true) {
        hueMEAN.push_back(vf);
        ContourPoints.push_back(points);
    }
}

drawContours(drawing, ContourPoints, -1, Scalar(255, 255, 255), 2, 8);

// Calculate Mean and STD for each Contour
cout << "contour Means & STD of Vec3b:" << endl;
for (int i = 0; i < hueMEAN.size(); i++) {

    Scalar meanTemp = mean(hueMEAN.at(i));
    Scalar sdTemp;
    cout << i << ": " << endl;
    cout << meanTemp << endl;
    cout << " " << endl;
    meanStdDev(hueMEAN.at(i), meanTemp, sdTemp);
    cout << sdTemp << endl;
    cout << " " << endl;
}
cout << "Actual Contours: " << contours.size() << endl;
cout << "# Contours: " << hueMEAN.size() << endl;

imshow("img", src);
imshow("HSV", HSV);
imshow("Edges", Edges);
imshow("contours", drawing);
waitKey(0);

return 0;
}
#包括
#包括
#包括
#包括
使用名称空间cv;
使用namespa