[Tutorial introductorio 6 de OpenCV] Cree la barra de seguimiento y ajuste el contraste de la imagen y el valor de brillo



Esta serie de artículos es producida por @ 浅 墨 _ 毛星云, indique la fuente para la reimpresión.
Enlace del artículo: http://blog.csdn.net/poem_qianmo/article/details/21176257
La versión de OpenCV utilizada al escribir la publicación actual del blog: 4.20

En este artículo, aprendimos cómo crear y usar barras de seguimiento con la función createTrackbar en OpenCV, así como el ajuste dinámico de los valores de contraste y brillo de la imagen.

El artículo primero explicó en detalle la función createTrackbar en la nueva versión de OpenCV2.0 y dio un ejemplo de un comentario detallado.

Luego, explique los detalles del ajuste de brillo y contraste de la imagen, y finalmente lanzó un código fuente de programa que usa la función createTrackbar para crear una barra de seguimiento para ayudar en el ajuste de brillo y contraste de la imagen.

Aún así, ponga una captura de pantalla de la operación primero:
Inserte la descripción de la imagen aquí
OK, comencemos oficialmente nuestra explicación.

1. La creación y uso de Trackbar en OpenCV

<1> Cree una barra de seguimiento: una explicación detallada de la función createTrackbar

La función createTrackbar se utilizará con frecuencia en el futuro. Crea una barra de seguimiento que puede ajustar el valor y adjunta la barra de seguimiento a la ventana especificada, que es muy conveniente de usar. En primer lugar, todos deben recordar que a menudo se usa junto con una función de devolución de llamada. Primero mire su prototipo de función:

C++: int createTrackbar(conststring& trackbarname, conststring& winname,
 int* value, int count, TrackbarCallback onChange=0,void* userdata=0);

El primer parámetro , trackbarname of const string & type, representa el nombre de la barra de seguimiento, que se utiliza para representar la barra de seguimiento que creamos.
El segundo parámetro , winname of const string & type, completa el nombre de la ventana, lo que indica a qué ventana se adjuntará la barra de seguimiento, que corresponde a un determinado nombre de ventana que se rellenó cuando namedWindow () crea la ventana.
El tercer parámetro , valor de tipo int *, un puntero a un número entero, que indica la posición del control deslizante. Y cuando se crea, la posición inicial del control deslizante es el valor actual de la variable.
El cuarto parámetro , recuento de tipo int, representa el valor de la posición máxima que puede alcanzar el control deslizante. PS: el valor de la posición más pequeña del control deslizante es siempre 0.
El quinto parámetro , onChange de TrackbarCallback tipo, primero observe que tiene un valor predeterminado de 0. Este es un puntero a una función de devolución de llamada. Esta función realizará una devolución de llamada cada vez que cambie la posición del control deslizante. Y el prototipo de esta función debe ser void XXXX (int, void *); el primer parámetro es la posición de la barra de seguimiento y el segundo parámetro son los datos del usuario (consulte el sexto parámetro a continuación). Si la devolución de llamada es un puntero NULL, significa que no hay una llamada a la función de devolución de llamada y solo ha cambiado el valor del tercer parámetro.
El sexto parámetro , datos de usuario de tipo void *, también tiene un valor predeterminado de 0. Este parámetro son los datos que el usuario pasa a la función de devolución de llamada para procesar los eventos de la barra de seguimiento. Si el tercer argumento de valor de parámetro utilizado es una variable global, puede ignorar el parámetro de datos de usuario.

Esta función createTrackbar crea una barra de seguimiento (Trackbar, o herramienta de control de rango deslizante) con un nombre y rango específicos para nosotros, y especifica una variable que está sincronizada con la posición de la barra de seguimiento. Y debe especificar la función de devolución de llamada onChange (el quinto parámetro), que se llama cuando cambia la posición de la barra de seguimiento. Y sabemos que la barra de seguimiento creada se muestra en la ventana representada por el nombre de win especificado (el segundo parámetro).

Después de leer la explicación de la función, primero le demos un pequeño ejemplo del uso de la función:

 //创建轨迹条
       createTrackbar("对比度:", "【效果图窗口】",&g_nContrastValue,
300,ContrastAndBright );// g_nContrastValue为全局的整型变量,ContrastAndBright为回调函数的函数名(即指向函数地址的指针)

Te dejamos un ejemplo completo de uso. Este es el programa de muestra oficial de OpenCV, un programa que demuestra el uso de las barras de seguimiento para controlar la detección de contornos y el relleno de contornos. Qianmo publica su modificación, simplificación de código y comentarios detallados para que todos puedan asimilar y estudiar. Habrá una explicación más detallada de la detección de contornos en la publicación de blog actualizada más adelante.

//-----------------------------------【头文件包含部分】---------------------------------------
//	描述:包含程序所依赖的头文件
//---------------------------------------------------------------------------------------------- 
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

//-----------------------------------【命名空间声明部分】---------------------------------------
//	描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------   
using namespace cv;
using namespace std;

//-----------------------------------【全局函数声明部分】--------------------------------------
//	描述:全局函数声明
//-----------------------------------------------------------------------------------------------
Mat img;
int threshval = 160;			//轨迹条滑块对应的值,给初值160

//-----------------------------【on_trackbar( )函数】------------------------------------
//	描述:轨迹条的回调函数
//-----------------------------------------------------------------------------------------------
static void on_trackbar(int, void*)
{
	Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);

	//定义点和向量
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;

	//查找轮廓
	findContours(bw, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
	//初始化dst
	Mat dst = Mat::zeros(img.size(), CV_8UC3);
	//开始处理
	if (!contours.empty() && !hierarchy.empty())
	{
		//遍历所有顶层轮廓,随机生成颜色值绘制给各连接组成部分
		int idx = 0;
		for (; idx >= 0; idx = hierarchy[idx][0])
		{
			Scalar color((rand() & 255), (rand() & 255), (rand() & 255));
			//绘制填充轮廓
			drawContours(dst, contours, idx, color, FILLED, 8, hierarchy);
		}
	}
	//显示窗口
	imshow("Connected Components", dst);
}


//-----------------------------------【main( )函数】--------------------------------------------
//	描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
	system("color 5F");
	//载入图片
	img = imread("1.jpg", 0);
	if (!img.data) { printf("Oh,no,读取img图片文件错误~! \n"); return -1; }

	//显示原图
	namedWindow("Image", 1);
	imshow("Image", img);

	//创建处理窗口
	namedWindow("Connected Components", 1);
	//创建轨迹条
	createTrackbar("Threshold", "Connected Components", &threshval, 255, on_trackbar);
	on_trackbar(threshval, 0);//轨迹条回调函数

	waitKey(0);
	return 0;
}

Imagen original:
Inserte la descripción de la imagen aquí
Imagen de efecto de ejecución:
Inserte la descripción de la imagen aquí

Arrastre la barra de desplazamiento para cambiar el valor de umbral (umbral) para obtener imágenes con diferentes efectos:

Inserte la descripción de la imagen aquí
Además, puede encontrar el código oficial original en la ruta OpenCV opencv_source_code / samples / cpp / connected_components.cpp.

Luego, por cierto, hablemos de una función que se usa con createTrackbar, la función getTrackbarPos que se usa para obtener la posición de la barra de seguimiento actual.

<2> Obtener la posición de la función actual barra de pista-getTrackbarPos

<2> Obtener la posición de la función actual barra de pista-getTrackbarPos

Esta función se utiliza para obtener la posición de la barra de seguimiento actual y devolverla.

El primer parámetro , trackbarname de tipo const string &, representa el nombre de la trackbar.
El segundo parámetro , winname de tipo const string &, representa el nombre de la ventana principal de la barra de seguimiento.

Probablemente eso sea todo para esta parte. Pasemos a la siguiente parte sin parar :)

2. Base teórica para el ajuste de brillo y contraste

Primero, damos el concepto de operadores. El operador general de procesamiento de imágenes es una función que acepta una o más imágenes de entrada y produce una imagen de salida. La siguiente fórmula da la forma general del operador:

Inserte la descripción de la imagen aquí
La operación de ajuste del brillo y el contraste de la imagen que estamos explicando hoy es en realidad un tipo relativamente simple de transformadores de procesamiento de imágenes: operadores. La operación de puntos tiene una característica, solo basada en el valor del píxel de entrada (a veces puede agregar alguna información o parámetros globales), para calcular el valor del píxel de salida correspondiente. Dichos operadores incluyen ajustes de brillo y contraste, así como correcciones y transformaciones de color.

Las dos operaciones puntuales más comúnmente utilizadas (u operadores puntuales), obviamente, son multiplicar por una constante (correspondiente al ajuste del contraste) y sumar una constante (correspondiente al ajuste del valor de brillo). La fórmula es así:

Inserte la descripción de la imagen aquí
Al ver esta fórmula, nuestra estrategia para el ajuste del brillo y el contraste de la imagen está lista para salir.

entre ellos:

** El parámetro f (x) ** representa el píxel de la imagen de origen.
El parámetro g (x) representa los píxeles de la imagen de salida.
El parámetro a (necesidad de satisfacer a> 0) se llama ganancia y se usa a menudo para controlar el contraste de la imagen.
El parámetro b generalmente se llama sesgo y se usa a menudo para controlar el brillo de la imagen.

Y un paso más cerca, reescribimos esta fórmula así:
Inserte la descripción de la imagen aquí
donde iyj indican que el píxel está ubicado en la i-ésima fila y j-ésima columna.

Entonces, esta fórmula se puede utilizar como fórmula teórica para controlar el brillo y el contraste de la imagen en OpenCV.

3. Acerca del acceso a los píxeles en las imágenes

Hay muchas formas de acceder a los píxeles de la imagen, y la tinta clara utilizará un tema para explicar en el futuro. En la actualidad, primero podemos entender el siguiente.

Para realizar esta operación, necesitamos acceder a cada píxel de la imagen. Debido a que la operación se realiza sobre imágenes GBR, cada píxel tiene tres valores (G, B, R), por lo que debemos acceder a ellos por separado (el modo de almacenamiento de imágenes en PS: OpenCV es GBR). El siguiente es un fragmento de código para acceder al píxel. Tres bucles for resuelven el problema:

//三个for循环,执行运算 new_image(i,j) =a*image(i,j) + b
       for(int y = 0; y < image.rows; y++ )
       {
              for(int x = 0; x < image.cols; x++ )
              {
                     for(int c = 0; c < 3; c++ )
                     {
                            new_image.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (g_nContrastValue*0.01)*(image.at<Vec3b>(y,x)[c] ) + g_nBrightValue );
                     }
              }
       }

Expliquemos en tres aspectos:

Para acceder a cada píxel de la imagen, usamos esta sintaxis: image.at (y, x) [c]

Entre ellos, y es la fila donde se encuentra el píxel, x es la columna donde se encuentra el píxel yc es uno de R, G y B (correspondiente a 0, 1, 2).

Debido a que el resultado de nuestro cálculo puede exceder el rango de valores de píxeles (desbordamiento), o puede ser un número no entero (si es un número de punto flotante), necesitamos usar saturate_cast para convertir el resultado y asegurarnos de que sea un valor válido.

Aquí, a es el contraste. Generalmente, el valor es un valor de punto flotante de 0.0 a 3.0 para el efecto de la observación, pero nuestra barra de seguimiento generalmente toma un valor entero, por lo que aquí podemos establecer el parámetro nContrastValue que representa el valor de contraste. es un número entero entre 0 y 300. Multiplica 0.01 en la fórmula final, para que puedas completar el cambio de 300 valores diferentes en la barra de seguimiento. Entonces, en la fórmula, veremos g_nContrastValue * 0.01 en saturate_cast ((g_nContrastValue 0.01) (image.at (y, x) [c]) + g_nBrightValue).

Cuatro, contraste de imagen, programa de muestra de ajuste del valor de brillo

Sigue siendo una publicación de blog anotada detallada que respalda el programa de muestra que se le asignará a cada artículo. Los puntos de conocimiento presentados en este artículo se utilizan como soporte para mostrarle el código.

Este programa de muestra utiliza dos barras de seguimiento para controlar los valores de contraste y brillo respectivamente, lo que tiene un cierto grado de jugabilidad. No hay mucha tontería, vayamos al código:

// 操作系统: Windows 10 64bit
// 开发语言: C++
// IDE 版 本:Visual Studio 2019
// OpenCV版本:4.20
//-----------------------------------【头文件包含部分】---------------------------------------
//	描述:包含程序所依赖的头文件
//---------------------------------------------------------------------------------------------- 
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

//-----------------------------------【命名空间声明部分】---------------------------------------
//	描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------   
using namespace std;
using namespace cv;


//-----------------------------------【全局函数声明部分】--------------------------------------
//	描述:全局函数声明
//-----------------------------------------------------------------------------------------------
static void ContrastAndBright(int, void*);
void   ShowHelpText();

//-----------------------------------【全局变量声明部分】--------------------------------------
//	描述:全局变量声明
//-----------------------------------------------------------------------------------------------
int g_nContrastValue; //对比度值
int g_nBrightValue;  //亮度值
Mat g_srcImage, g_dstImage;
//-----------------------------------【main( )函数】--------------------------------------------
//	描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
	//改变控制台前景色和背景色
	system("color 2F");

	// 读入用户提供的图像
	g_srcImage = imread("1.jpg");
	if (!g_srcImage.data) { printf("读取g_srcImage图片错误~! \n"); return false; }
	g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type());

	//设定对比度和亮度的初值
	g_nContrastValue = 80;
	g_nBrightValue = 80;

	//创建窗口
	namedWindow("【效果图窗口】", 1);

	//创建轨迹条
	createTrackbar("对比度:", "【效果图窗口】", &g_nContrastValue, 300, ContrastAndBright);
	createTrackbar("亮   度:", "【效果图窗口】", &g_nBrightValue, 200, ContrastAndBright);

	//调用回调函数
	ContrastAndBright(g_nContrastValue, 0);
	ContrastAndBright(g_nBrightValue, 0);

	//输出一些帮助信息
	cout << endl << "\t运行成功,请调整滚动条观察图像效果\n\n"
		<< "\t按下“q”键时,程序退出\n";

	//按下“q”键时,程序退出
	while (char(waitKey(1)) != 'q') {}
	return 0;
}


//-----------------------------【ContrastAndBright( )函数】------------------------------------
//	描述:改变图像对比度和亮度值的回调函数
//-----------------------------------------------------------------------------------------------
static void ContrastAndBright(int, void*)
{

	// 创建窗口
	namedWindow("【原始图窗口】", 1);

	// 三个for循环,执行运算 g_dstImage(i,j) = a*g_srcImage(i,j) + b
	for (int y = 0; y < g_srcImage.rows; y++)
	{
		for (int x = 0; x < g_srcImage.cols; x++)
		{
			for (int c = 0; c < 3; c++)
			{
				g_dstImage.at<Vec3b>(y, x)[c] = saturate_cast<uchar>((g_nContrastValue * 0.01) * (g_srcImage.at<Vec3b>(y, x)[c]) + g_nBrightValue);
			}
		}
	}

	// 显示图像
	imshow("【原始图窗口】", g_srcImage);
	imshow("【效果图窗口】", g_dstImage);
}

Finalmente, eche un vistazo a las capturas de pantalla de la operación.Cuando ejecute este programa, obtendrá dos ventanas de visualización de imágenes. La primera es la ventana de la imagen original y la segunda es la ventana de la imagen del efecto. Se pueden ajustar dos barras de seguimiento en la ventana de la imagen del efecto para cambiar el contraste y el brillo de la imagen actual.

Imagen original:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/m0_51233386/article/details/114667113
Recomendado
Clasificación