Well, you did not provide important details of your problem (for example: What type of image is it? Is the red color pure red, or is it a range of shades of red?) and it is also unclear what you really want when you say "the program returns to it the area" (the program calculates the area in pixels? the program highlights the area with another color? etc). So I made a simple example that can help you start to understand the problem. It uses simple operations, in which you search and change the pixel values by comparing them to a desired color.
In the following code example, I look for the EXACT red color (in BGR code - the one used by Opencv - that means (0, 0, 255), because it is 0 for blue/blue, 0 for green/green and 255 for red/red), count the number of pixels that have this color and I already replace them with another color given (in the example, yellow, to highlight the change):
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <string>
#include <iomanip>
#include <iostream>
using namespace std;
using namespace cv;
/**
* Conta o número de pixels na imagem com a primeira cor e os substitui pela segunda cor.
* @param oImagem cv::Mat com os dados da imagem colorida.
* @param oCor cv::Vec3b com os valores BGR dos pixels a serem contados/substituidos.
* @param oNovaCor cv::Vec3b com os valores BGR para substituir os pixels encontrados.
* @return Retorna um inteiro com o número de pixels encontrados com a cor dada.
*/
int processaCorExata(Mat &oImagem, Vec3b oCor, Vec3b oNovaCor)
{
Vec3b oPixel;
int iPixels = 0;
for (int x = 0; x < oImagem.size().width; x++)
{
for (int y = 0; y < oImagem.size().height; y++)
{
oPixel = oImagem.at<Vec3b>(y, x);
// Checa se o pixel tem EXATAMENTE a mesma cor
if (oPixel[0] == oCor[0] && oPixel[1] == oCor[1] && oPixel[2] == oCor[2])
{
iPixels++; // Contabiliza o pixel
oImagem.at<Vec3b>(y, x) = oNovaCor; // Substitui pela nova cor dada
}
}
}
return iPixels;
}
/**
* Função principal.
* @param argc Inteiro com o número de argumentos da linha de comando.
* @param argv Lista de strings com os argumentos da linha de comando.
* @return Retorna um inteiro com o código de erro ou 0 se encerrado com sucesso.
*/
int main(int argc, char** argv)
{
// Carrega a imagem colorida de exemplo
Mat oImagem = imread("C:/Temp/rgb.png", CV_LOAD_IMAGE_COLOR);
if (!oImagem.data)
{
cout << "Erro carregando a imagem" << endl;
return -1;
}
// Exibe a imagem original em uma janela
namedWindow("Imagem Original", WINDOW_AUTOSIZE);
imshow("Imagem Original", oImagem);
// Definição das cores
Vec3b oVermelho(0, 0, 255);
Vec3b oAmarelo(0, 255, 255);
// Conta os pixels em vermelho e os substitui por amarelo
int iPixels = processaCorExata(oImagem, oVermelho, oAmarelo);
// Calcula a área em vermelho (número de pixels e percentual sobre a área total da imagem)
int iAreaTotal = oImagem.size().width * oImagem.size().height;
ostringstream sMsgBuilder;
sMsgBuilder << "Pixels vermelhos: " << iPixels;
sMsgBuilder << " (" << std::fixed << std::setprecision(2) << (iPixels / (float)iAreaTotal) * 10.0 << "%)";
string sMsg = sMsgBuilder.str();
// Exibe essa informação na saída padrão e também na imagem
cout << sMsg << endl;
double dScale = 0.5;
int iThickness = 3;
int iFontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;
int iBaseline = 0;
Size oSize = getTextSize(sMsg.c_str(), iFontFace, dScale, iThickness, &iBaseline);
iBaseline += iThickness;
Point oPos(iThickness, oImagem.rows - oSize.height - iThickness);
putText(oImagem, sMsg.c_str(), oPos, FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, Scalar::all(0));
// Exibe a imagem processada em uma nova janela
namedWindow("Imagem Processada", WINDOW_AUTOSIZE);
imshow("Imagem Processada", oImagem);
// Aguarda o usuário fechar as janelas ou pressionar qualquer tecla
waitKey(0);
return 0;
}
The sample image used in my tests is this:
That after processing generates the following result:
IMPORTANT: Note, however, that this program will not work as expected for images with more distinct colors (i.e., other shades of red). There are alternatives, of course, for these cases. You can try to do liming (see function threshold
from Opencv), or generate vc even masks with larger thresholds and directly use the function inRange
Opencv (a more recommended method than doing the manipulations I exemplify in the above code, if the images of your problem domain are really more complex).
P.S.: The logic is the same as those of my other answers in C# and
in Java.