Directorio de artículos
-
- 1. Función de separación de canales split()
- 2. Función de combinación de canales merge()
-
- Prototipo de función:
-
- (1) Prototipo de función 1: la entrada son los datos de la imagen `Mat mvbegin[3]` en forma de una matriz Mat
- (2) Prototipo de función 2: la entrada son los datos de la imagen en forma de contenedor vectorial `vector <Mat>`
- (3) Ejemplo 1: Primero use split() para separar los tres canales de la imagen, use la matriz de tipo Mat `Mat mvbegin[3]` para almacenar la imagen separada y luego fusione las imágenes de tres canales con merge() , correspondiente al prototipo de función 1 ;
- (4) Ejemplo 2: primero use split() para separar los tres canales de la imagen, use el contenedor vectorial `vector <Mat>` para almacenar la imagen separada y luego use merge() para fusionar las imágenes de tres canales, correspondiente al prototipo de función 2;
- 3. Mezcla de canales mixChannels()
La función imread predeterminada en opencv carga archivos de imagen, y la imagen cargada es una imagen en color de tres canales, el espacio de color es el espacio de color RGB y el orden de los canales es BGR (azul, verde, rojo). , OpenCV proporciona tres API. La función se utiliza para realizar la separación de canales split(), merge() y mixChannels();
Imagen RGB, en Mat de opencv, datos de píxeles, estructura de almacenamiento y separación de canales, el diagrama de relación de operación es el siguiente:
1. Función de separación de canales split()
Prototipo de función:
El uso de los dos prototipos de funciones es el mismo, y se utiliza para separar imágenes multicanal en varias imágenes de un solo canal. La diferencia entre los dos prototipos de funciones es que las imágenes separadas de un solo canal tipo Mat se almacenan en Mat -tipo matrices,
Mat mvbegin[3]
o Almacenado en un contenedor de vectores,vector <Mat> mv
;
La función split() en OpenCV 4 tiene 2 prototipos sobrecargados:
(1) Prototipo de función 1: use una matriz de tipo Mat Mat mvbegin[3]
para almacenar la imagen separada;
void split( const Mat &src, Mat *mvbegin )
Parámetros de entrada:
- src: imagen a separar, matriz multicanal tipo Mat;
- mvbegin: imagen de un solo canal de tipo Mat separada, almacenada en una matriz de tipo Mat,
Mat mvbegin[3]
al definir el tamaño de la matriz, debe saber la cantidad de canales de la imagen original, tamaño de la matriz = número de canales de la imagen original; - Las imágenes separadas se almacenan en una matriz de tipo Mat
Mat mvbegin[3]
. Los tres elementos de la matriz son matrices de tipo Mat con el tamaño de image.rows X image.cols, que almacenan los datos de los componentes B, G y R de la imagen original a su vez, y tome la matriz Los elementos dentro solo pueden ser[]
valorados por , no porat()
;
(2) Prototipo de función 2: use un contenedor de vectores vector <Mat>
para almacenar imágenes separadas;
void split( InputArray m, OutputArrayOfArrays mv )
Parámetros de entrada:
- m: imagen a separar, Matriz multicanal tipo Mat;
- mv: Imagen monocanal separada tipo Mat, almacenada en un contenedor vectorial,
vector <Mat> mv
no necesita saber el número de canales de la imagen original; - La imagen separada se almacena en el contenedor vectorial.
vector <Mat> mv
Hay 3 elementos en el contenedor mv, y el tamaño de cada elemento es una matriz tipo Mat de image.rows X image.cols, que almacena los componentes B, G y R de la imagen original a su vez Datos, cada elemento se puede obtener por[]
valor, o porat()
valor;
(3) Ejemplo:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
// 读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);
// 用Mat型数组,存储分离后的图像,只能用 [] 访问
// Mat mvbegin[3];
// split(src, mvbegin);
// imshow("B", mvbegin[0]);
// imshow("G", mvbegin[1]);
// imshow("R", mvbegin[2]);
// 用vector容器,存储分离后的图像,用 [] 访问
// vector<Mat> mv;
// split(src, mv);
// imshow("B", mv[0]);
// imshow("G", mv[1]);
// imshow("R", mv[2]);
// 用vector容器,存储分离后的图像,用 at() 访问
vector<Mat> mv;
split(src, mv);
imshow("B", mv.at(0));
imshow("G", mv.at(1));
imshow("R", mv.at(2));
waitKey();
destroyAllWindows();
return 0;
}
resultado de la operación:
2. Función de combinación de canales merge()
- El uso de los dos prototipos de funciones es el mismo, que se utiliza para combinar varias imágenes (imágenes de un solo canal o de varios canales) en una imagen de varios canales. La diferencia entre los dos prototipos de funciones es que la entrada son los datos de la imagen. en forma de matriz Mat,
Mat mvbegin[3]
o datos de imagen en forma de contenedor vectorialvector <Mat>
, que corresponde al prototipo de la función split();- La salida de la función de fusión es una imagen multicanal, y su número de canales es la suma del número de canales de todas las imágenes de entrada. Las imágenes utilizadas para la fusión no son todas de un solo canal, sino que también pueden ser multicanal. imágenes. El número de canales de la imagen de entrada puede ser diferente. Igual, pero requiere que todas las imágenes sean del mismo tamaño y tipo de datos;
Prototipo de función:
(1) Prototipo de función 1: la entrada son datos de imagen en forma de matriz MatMat mvbegin[3]
void merge( const Mat *mvbegin, size_tcount, OutputArray dst )
Parámetros de entrada:
- mvbegin: imágenes de un solo canal o de varios canales que deben fusionarse, la entrada son datos de una imagen en forma de una matriz Mat
mvbegin[3]
; - size_tcount: la longitud de la matriz de imágenes de entrada, su valor debe ser mayor que 0;
- dst: imagen fusionada;
(2) Prototipo de función 2: la entrada son datos de imagen en forma de contenedor vectorialvector <Mat>
void merge( InputArrayOfArrays mv, OutputArray dst )
Parámetros de entrada:
- mv: las imágenes de un solo canal o de varios canales que deben fusionarse. La entrada son datos de una imagen en forma de contenedor vectorial
vector <Mat>
, donde cada imagen debe tener el mismo tamaño y tipo de datos; - dst: la imagen fusionada
mv[0]
tiene el mismo tamaño y tipo de datos, y la cantidad de canales es igual a la suma de la cantidad de canales de todas las imágenes de entrada;
(3) Ejemplo 1: use split() para separar la imagen en tres canales, Mat mvbegin[3]
almacene la imagen separada en una matriz tipo Mat y luego fusione las imágenes de tres canales con merge(), correspondiente al prototipo de función 1;
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
// 读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);
// 通道分离,用Mat型数组存储分离后的图像
Mat mvbegin[3];
split(src, mvbegin);
Mat BlueChannel = mvbegin[0];
Mat GreenChannel = mvbegin[1];
Mat RedChannel = mvbegin[2];
// 将R通道全部置0
Mat r = mvbegin[2].clone();
r.setTo(0);
// 需要合并的Mat型数组
Mat newChannel[3] = {
BlueChannel , GreenChannel , r };
// 合并通道
Mat dst;
merge(newChannel, 3, dst);
// 显示
imshow("Merged", dst);
waitKey();
destroyAllWindows();
return 0;
}
resultado de la operación:
(4) Ejemplo 2: primero use split() para separar los tres canales de la imagen, use el contenedor de vectores para vector <Mat>
almacenar la imagen separada y luego combine las imágenes de tres canales con merge(), correspondiente a la función prototipo 2;
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
// 读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);
// 通道分离
vector<Mat> mv;
split(src, mv);
Mat BlueChannel = mv.at(0);
Mat GreenChannel = mv.at(1);
Mat RedChannel = mv.at(2);
// 将B通道全部置0
Mat b = mv.at(0).clone();
b.setTo(0);
vector<Mat> newChannel;
newChannel.push_back(b);
newChannel.push_back(GreenChannel);
newChannel.push_back(RedChannel);
//通道合并
Mat mergedImage;
merge(newChannel, mergedImage);
// 显示
imshow("Merged", mergedImage);
waitKey();
destroyAllWindows();
return 0;
}
resultado de la operación:
3. Mezcla de canales mixChannels()
Prototipo de función:
(1) Prototipo de función uno:
void cv::mixChannels (
InputArrayOfArrays src,
InputOutputArrayOfArrays dst,
const std::vector< int > &fromTo
)
Parámetros de entrada:
- src: matriz de entrada, todas las matrices deben tener el mismo tamaño y profundidad;
- dst: matriz de salida, el tamaño y la profundidad deben ser los
src[0]
mismos que; - fromTo: par de índices, que indica en qué canal de la matriz de entrada se copia, en qué canal de la matriz de salida; por ejemplo: {
0, 2, 1, 1, 2, 0 } significa:
src color el canal 0 se copia en dst Color canal 2
src color canal 1 copiado a dst color canal 1
src color canal 2 copiado a dst color canal 0
(2) Prototipo de función 2:
En este prototipo de función:
- Si la matriz de entrada y la matriz de salida son ambas 1, entonces es consistente con el prototipo de la primera función;
- Si no es 1, se pueden fusionar múltiples matrices, o una matriz se puede dividir en múltiples matrices u otras funciones;
void cv::mixChannels
(
const Mat *src,
size_t nsrcs,
Mat *dst,
size_t ndsts,
const int *fromTo,
size_t npairs
)
Parámetros de entrada:
- src: matriz de entrada, todas las matrices deben tener el mismo tamaño y profundidad;
- ndsts: número de matrices;
- dst: matriz de salida, el tamaño y la profundidad deben ser los
src[0]
mismos que; - fromTo: par de índices, que indica en qué canal de la matriz de entrada, copiado, en qué canal de la matriz de salida;
- ndsts: número de matrices;
- npairs: el número de pares de índices en fromTo;
(3) Ejemplo 1: Cambio de canal de color cian (255, 255, 0) amarillo (0, 255, 255)
El color cian (255, 255, 0) de la imagen original se copia en la imagen de salida a través del canal especificado y se vuelve amarillo (0, 255, 255);
Canal de correspondencia:
El significado del par de índices from_to[] = { 0, 2, 1, 1, 2, 0, 3, 3 }:
- Canal 0 de bg, copiado al canal 2 de out[], es decir, canal 0 de bgr;
- Canal 1 de bgra, copiado al canal 1 de out[], es decir, canal 1 de bgr;
- Canal 2 de bgra, copiado al canal 0 de out[], es decir, canal 2 de bgr;
- Los 3 canales de bgra, copiados a, los 3 canales de out[], es decir, el canal alfa de bgr;
Código de muestra:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
// 读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);
Mat bgra(200, 200, CV_8UC4, Scalar(255, 255, 0, 255));
Mat bgr(bgra.rows, bgra.cols, CV_8UC3);
Mat alpha(bgra.rows, bgra.cols, CV_8UC1);
Mat out[] = {
bgr, alpha };
int from_to[] = {
0, 2, 1, 1, 2, 0, 3, 3 };
mixChannels(&bgra, 1, out, 2, from_to, 4);
imshow("bgra", bgra);
imshow("bgr", bgr);
waitKey();
destroyAllWindows();
return 0;
}
resultado de la operación:
(4) Ejemplo 2: Segmentación de imágenes
Divida una matriz de 4 canales (imagen BGRA) en una matriz de 3 canales (imagen BGR) y una matriz de un solo canal (imagen de canal alfa);
Correspondencia de canales: par de índices, int fromTo[] = { 0, 2, 1, 1, 2, 0, 3, 3 }
- Canal 0 de bgra, copiado al canal 2 de bgr;
- Canal 1 de bgra, copiado al canal 1 de bgr;
- Canal 2 de bgra, copiado al canal 0 de bgr;
- Canal 3 de bgra, copiado al canal 0 de alfa;
Código de muestra:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
Mat bgra( 200, 200, CV_8UC4, Scalar(255, 0, 0, 255) );
Mat bgr( bgra.rows, bgra.cols, CV_8UC3 );
Mat alpha( bgra.rows, bgra.cols, CV_8UC1 );
Mat out[] = {
bgr,alpha };
// 通道对应关系
int fromTo[] = {
0, 2, 1, 1, 2, 0, 3, 3 };
mixChannels(&bgra, 1, out, 2, fromTo, 4);
imshow("bgra", bgra);
imshow("bgr", bgr);
imshow("alpha", alpha);
waitKey();
destroyAllWindows();
return 0;
}
resultado de la operación:
(5) Ejemplo 3: Adquisición de canal HSV
Utilice la función mixChannels() para copiar el canal especificado y podrá ver los detalles de los tres canales en el espacio de color HSV;
Espacio de color HSV:
- Hue (tono): representa el color, medido de 0 a 360 grados (rojo-amarillo-verde-cian-azul-magenta);
- Saturación (saturación, croma): se refiere a la profundidad del color. La saturación representa la proporción de gris a tono, y se mide desde 0 % (gris) hasta 100 % (saturación total). Cuando S=0, solo hay gris escala;
- Valor (tono): el brillo del color, V=1, que incluye las tres caras de R=1, G=1 y B=1 en el modelo RGB, y el color representado es más brillante;
Código de muestra:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
// 读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);
Mat hsv, dst;
cvtColor(src, hsv, COLOR_BGR2HSV);
dst.create( hsv.size(), hsv.depth() );
//分离Hue,色相通道
int ch[] = {
0, 0 };
mixChannels(&hsv, 1, &dst, 1, ch, 1);
imshow("H channel", dst);
//分离Saturation,饱和度通道
int ch1[] = {
1, 0 };
mixChannels(&hsv, 1, &dst, 1, ch1, 1);
imshow("S channel", dst);
//分离Value,色调通道
int ch2[] = {
2, 0 };
mixChannels(&hsv, 1, &dst, 1, ch2, 1);
imshow("V channel", dst);
waitKey();
destroyAllWindows();
return 0;
}