Ir ao conteúdo

Posts recomendados

Postado

Ola estou com um projeto de um programa que compara um print de tela com outra imagem semelhante e mostra as diferenças. Preciso saber como posso fazer isso entao pensei que seja possivel abrir os pixels da imagem para comparar. Ate o momento so tenho experiencia em c e c++, deveria migrar para outra linguagem para tentar solucionar isso ou é possivel?.se possivel sera que precisaria de alguma biblioteca especial tipo a allegro ou outra que trabalhe com imagem? Nao pretendo utilizar IA quero algo bem simples. Por onde devo começar?

Para evitar que o o primeiro comentario alguem diga que nao entendeu o projeto e explique mais. Eu preciso apenas distinguir a posicao de um imagem na tela por exemplo: salvarei 2 imagens: na primeiro tenho uma imagem posicionada a esquerda e na outra a mesma imagem a direita. Entao vou tirar um print e o programa ira comparar e dizer se no print a imagem esta a esquerda ou direita ou informar que nao foi encontrada a imagem. 

  • Amei 1
Postado

@Mayrinck Bernardo       na linguagem c e c++ , voce pode fazer a comparacao de cada pixel de uma determinada area com outra ,

se voce souber a posicao de cada uma na tela ,  comparando o valor RGB de cada pixel e com isso verificar se as duas sao iguais ,  entao voce precisarah usar comandos mais avancados do que os usados no console ,  e para isso voce pode usar a API do windows ,  criando um projeto do tipo win32 GUI , e ali use o comando getpixel para pegar o valor RGB do pixel ,  e com os comandos  Rvalue , Gvalue e Bvalue , voce consegue saber a quantidade de cor vermelha , verde e azul  que cada um tem   ,   mas dependendo do tamanho da imagen vai demorar bastante para verificar todos os pixeis ,  faca seu codigo e poste aqui , para vermos como esta e em que podemos ajudar     .

  • Obrigado 1
  • Haha 1
Postado
Em 16/01/2020 às 18:55, devair1010 disse:

 entao voce precisarah usar comandos mais avancados do que os usados no console ,  e para isso voce pode usar a API do windows ,  criando um projeto do tipo win32 GUI , e ali use o comando getpixel para pegar o valor RGB do pixel

 

@devair1010 as imagens pela definição do tópico já foram capturadas. Não vão estar na tela e não há "pixels" mais. Apenas bits na prática. Pode-se usar uma aplicação de console e nem precisa de uma interface especial: apenas a linha de comando fornecendo os nomes das duas telas capturadas e uma terceira com a imagem alvo.

 

Em 14/01/2020 às 13:49, Mayrinck Bernardo disse:

print de tela com outra imagem semelhante e mostra as diferenças

 

Dependendo de sua definição de semelhança isso pode ser mesmo o diabo pra escrever e seria o caso de treinar um modelo AI mesmo para reconhecer o padrão.

 

Mas se for para procurar algo igual no sentido matemático provavelmente não.

 

Seria melhor postar as tais imagens e definir essa noção de semelhança antes de tudo.

 

FORMATO  DE CAPTURA

 

É essencial saber o formato da captura. Definido o formato basta ler as especificações e escrever o código. Ou mesmo usar alguma biblioteca. Fiz algo assim em C e C++ para BMP e JPG então tenho alguns documentos. E classes talvez. Anexo uma versão resumida do formato para JPG e pode ajudar a ter uma ideia para esse formato. Tenho mais material. Escreva mais sobre o projeto

 

 

JPEG File Interchange Format 1.02.pdf

  • Obrigado 2
Postado

@devair1010 @arfneto mas o que seria mais preciso, o que me daria uma resposta mais rápida? um print capturado na hora e comparado com uma imagem já salva. ou uma interação em tempo real com a tela do meu ocmputador se é que isso é possivel? eu pretendo que o programa me der uma resposta em menos de 2 segundos

adicionado 17 minutos depois

 @vangodp pretendo criar alguns bots para games então pretendo capturar posição dos personagem e fazer alguma ação de acordo. mas não pretendo criar um controlador automatico e nem nada de complicado acho que apenas um printf me informando a posição seria algo extraordinário

  • Curtir 1
Postado

Trata-se de uma imagem em movimento? É muito diferente isso. O game tem luz, reflexos, sombras... Se está falando em buscar polígonos na imagem é uma coisa, se está falando em procurar um personagem que se move para decidir se ele está na tela é outra...

 

2s é um tempo e tanto para comparar as imagens, mas a história pode ser outra. Como vai salvar essa imagem? Em que formato? Qual a resolução do jogo? Interferir com o jogo para capturar a tela é outra história. Como vai fazer?

 

  • Curtir 1
  • Obrigado 1
Postado

Quero muito ter essa experiencia. Estou buscando alguns cursos que falam de graficos no youtube mas nao estão me ajudando muito.

Nao consigo entender como explicar uma regiao especifica para o programa e fazer me retornar o resultado esperado mas tenho fé que nesse ano de 2020 vou alcançar esses objetivos.  Nao que tenho assim um game especifico mas tenho exemplos que quero desenvolver trabalhando apenas com imagens.

 

Nessa primeira imagem ilustrativa tem na tela a imagem de um game famoso mmorpg. No seu canto inferior direito ha uma pequena aba chamada battle que apresenta a presença de criaturas proximas ao personagem e caso nao haja criatura fica vazia. Ok entao e fácil programar eu so tenho 2 casos que é vazio ou nao vazio independente de tipo de criatura. If naovazio Printf " uma criatura surgiu". Ok parece simples.É muito fácil encontrar na internet varios programas executaveis e injetaveis que fazem muito mais do que isso atacando diretamente o jogo e mudando completamente. mas trabalhar apenas com imagens me parece ser muito mais inteligente. entao vamos para mais o outro exemplo.

 

Na segunda imagem temos um famoso game java jogado diretamente pelo browser. No canto superior direito ha um pequeno mapa que resume toda a fase que estiver sendo jogada no momento. onde seu personagem é resumido em um pequeno ponto azul(alguns amigos do time tambem), e seu inimigo em um ponto vermelho. E todo enrredo se resume em saber a distancia exata de um ponto para o outro. O unico misterio que quero entender é fazer o console reconhecer meu pontinho azul e o pontinho vermelho lembrando que tenho 10 segundos para fazer a jogada e as fases sao aleatorias.

15872.2644.1692.1a.500.jpg

images.jpeg

  • Obrigado 1
  • 2 semanas depois...
Postado

@Mayrinck Bernardo      o programa em c++ poderia ser assim  :

#include <stdio.h>
#include <conio.h>
#include <Windows.h>
#define H GetStdHandle(STD_OUTPUT_HANDLE)
/*
    no codeblocks coloque esse -lgdi32 em
    settings/compiler / linker settings/ other linker options
*/
void gotoxy(int x, int y){
    COORD c;
    c.X = x;
    c.Y = y;
    SetConsoleCursorPosition( H,c );
}
int main(){
    POINT p;
    HDC tela = GetDC(0);
    while( ! GetAsyncKeyState( VK_INSERT ) ){
        GetCursorPos( &p );
        COLORREF    clrf  ;
        tela  = GetDC(0)  ;
        clrf  = GetPixel(tela,p.x,p.y);
        int r = GetRValue(clrf);
        int g = GetGValue(clrf);
        int b = GetBValue(clrf);
        gotoxy(0,5);
        printf("/* Pressione insert para parar */\n\n"    );
        printf("Quantidade de vermeelho ====> %d   \n"  ,r);
        printf("Quantidade de verde ========> %d   \n"  ,g);
        printf("Quantidade de azul =========> %d   \n\n",b);
        printf("posicao X da tela ==========> %d   \n",p.x);
        printf("posicao Y da tela ==========> %d   \n",p.y);
        Sleep(150);
    }
    ReleaseDC(0,tela);
    return 0;
}

          ali você precisa pegar os pixeis daquela posição da tela onde estão aqueles dois quadrados azul e guardar em um vetor , os valores de vermelho e azul e verde , de cada  pixel para saber o valor deles e depois quando o jogo estiver rodando vai pegando os pixeis  daquela posição e comparando com os valores guardados no vetor , e se algum deles não for igual é por que não tem quadrado azul . mas para esse programa interagir com o jogo , aí é outra coisa ,  e não tenho ideia de como seria .

Postado

Eu sei que já perguntei isso, mas em que formato vai gravar essas imagens?
Você não vai ter controle sobre o jogo então precisa antes de tudo encontrar a janela do jogo na tela. Como tem interesse em imagens de certo modo estáticas é bem mais simples. Nesse caso que descreveu apenas tem interesse em um painel estático. É muito diferente de acompanhar a tela como seria o caso de buscar um sprite ou ou um personagem em movimento. Apenas precisa identificar a janela e a partir dela identificar onde está esse painel e ir atrás das cores. Isso vai se resumir a buscar as informações de cor para um certo pedaço da janela.
A cor em geral é codificada como 4 bytes de cor para cada pixel. Um formato comum é o chamado RGBA onde você tem os valores para vermelho, verde, azul e um " canal alpha" que é um canal de transparência.

  • Curtir 1
Postado

@arfneto       pelo que o  @Mayrinck Bernardo    disse , o que ele quer mesmo é verificar se na tela do jogo aparece aquele quadrado vermelho , lá no mapa do jogo na parte de cima da tela à direita , e calcular a distancia do quadrado azul para o quadrado vermelho ,  então ele não vai realmente gravar essas imagens . 

Postado
Em 14/01/2020 às 13:49, Mayrinck Bernardo disse:

Ola estou com um projeto de um programa que compara um print de tela com outra imagem semelhante e mostra as diferenças. Preciso saber como posso fazer isso entao pensei que seja possivel abrir os pixels da imagem para comparar

 

Algo assim?

12 horas atrás, devair1010 disse:

@arfneto       pelo que o  @Mayrinck Bernardo    disse , o que ele quer mesmo é verificar se na tela do jogo aparece aquele quadrado vermelho , lá no mapa do jogo na parte de cima da tela à direita , e calcular a distancia do quadrado azul para o quadrado vermelho ,  então ele não vai realmente gravar essas imagens . 

 

Como vai comparar se não salvou? Mesmo que esteja na memória tem que estar em algum formato...

  • Curtir 1
  • Obrigado 1
Postado

No caso de gravar os pixels na memória no formato clássico RGBA veja a saída

Valor original: 123456ff
vermelho: 00000012
   verde: 00000034
    azul: 00000056
    alfa: 000000ff

desse programa 

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
	//	0x123456FF
	{
		unsigned int color = 0x123456FF;
		int red =   (color & 0xFF000000) >> 24;
		int green = (color & 0x00FF0000) >> 16;
		int blue =  (color & 0x0000FF00) >> 8;
		int alpha = (color & 0x000000FF);
		cout << "Valor original: " << setfill('0') 
			                             << setw(8) << hex << color << endl;
		cout << "vermelho: " << setfill('0') << setw(8) << hex << red << endl;
		cout << "   verde: " << setfill('0') << setw(8) << hex << green << endl;
		cout << "    azul: " << setfill('0') << setw(8) << hex << blue << endl;
		cout << "    alfa: " << setfill('0') << setw(8) << hex << alpha << endl;
	}
	return 0;
}

e vai entender como montar os pixels

 

Essa outra classe aqui grava bitmaps. Veja essas funções em especial

	void fillBitmap(uint8_t, uint8_t, uint8_t);
	void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue);

Para definir um pixel --- setPixel() ---ou encher um bitmap --- fillBitmap() --- com uma cor RGB

#include <fstream>
#include <string>
#include <cstdint>
#include <memory>

using namespace std;
#pragma pack(push, 2)

class Bitmap
{
private:
	struct FileHeader
	{
		char header[2]{ 'B', 'M' };
		int32_t fileSize;
		int32_t reserved{ 0 };
		int32_t dataOffset;
	};

private:
	struct InfoHeader {
		int32_t headerSize{ 40 };
		int32_t width;
		int32_t height;
		int16_t planes{ 1 };
		int16_t bitsPerPixel{ 24 };
		int32_t compression{ 0 };
		int32_t dataSize{ 0 };
		int32_t horizontalResolution{ 2400 };
		int32_t verticalResolution{ 2400 };
		int32_t colors{ 0 };
		int32_t importantColors{ 0 };
	};

private:
	int data_size{ 0 };
	int width{ 0 };
	int height{ 0 };
	unique_ptr<uint8_t[]> pPixels{ nullptr };

public:
	Bitmap(int width, int height);
	virtual ~Bitmap();

public:
	void fillBitmap(uint8_t, uint8_t, uint8_t);
	void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue);
	bool write(string filename);
};
#pragma pack(pop)

using namespace std;

Bitmap::Bitmap(int width, int height) :
	data_size(width*height*3),
	width(width),
	height(height),
	pPixels( new uint8_t[data_size] { } )
{}	// end Bitmap(int,int)


Bitmap::~Bitmap()
{}


bool Bitmap::write(string filename)
{
	FileHeader fileHeader;
	InfoHeader infoHeader;

	fileHeader.fileSize = sizeof(FileHeader) + sizeof(InfoHeader) + data_size;
	fileHeader.dataOffset = sizeof(FileHeader) + sizeof(InfoHeader);
	infoHeader.width = width;
	infoHeader.height = height;

	ofstream file;
	file.open(filename, ios::out | ios::binary);
	if (!file) return false;

	file.write((char*)&fileHeader, sizeof(fileHeader));
	file.write((char*)&infoHeader, sizeof(infoHeader));
	file.write((char*)pPixels.get(), data_size);
	file.close();

	if (!file)	return false;
	return true;
}

void Bitmap::fillBitmap(uint8_t red, uint8_t green, uint8_t blue)
{
	uint8_t* pPixel = nullptr;
	for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
		{
			pPixel = pPixels.get() + (y * 3) * width + (x * 3);
			pPixel[2] = red;
			pPixel[1] = green;
			pPixel[0] = blue;
		};	// for x
};	// fillBitmap()


void Bitmap::setPixel
(
	int x, int y, 
	uint8_t red, uint8_t green, uint8_t blue
)
{
	uint8_t* pPixel = pPixels.get();
	pPixel += (y * 3) * width + (x * 3);
	pPixel[0] = blue;
	pPixel[1] = green;
	pPixel[2] = red;
	return;
};	// setPixel()

Esse programa por exemplo gera dois bitmaps e pode ver que comparar não é complexo: basta endereçar os pixels como está em setPixel()


int main(int argc, char** argv)
{
	Bitmap bitmap(800, 600);
	bitmap.write("test.bmp");
	bitmap.fillBitmap(128, 128, 128);
	bitmap.write("test128.bmp");
	cout << "Finished." << endl;
	return 0;
}	// main()

 

  • Curtir 1
  • Obrigado 1
  • 4 semanas depois...
Postado

@arfneto    tentei usar seu código para manipular uma imagem , mas não esta´dando certo ,  o que será que está acontecendo nesse código  :

#include <fstream>
#include <string>
#include <stdint.h>
#include <memory>

using namespace std;
#pragma pack(push, 2)

class Bitmap
{
private:
	struct FileHeader
	{
		/*char header[2]{ 'B', 'M' };    -> aqui deu erro
		char header[2];                  -> tentei fazer assim
		header[0]= 'B';                  -> mas também
		header[1]= 'M';                  -> deu outro erro */
		int32_t fileSize;
		int32_t reserved/*{ 0 }*/;
		int32_t dataOffset;
	};

private:
	struct InfoHeader {
		int32_t headerSize{ 40 };
		int32_t width;
		int32_t height;
		int16_t planes{ 1 };
		int16_t bitsPerPixel{ 24 };
		int32_t compression{ 0 };
		int32_t dataSize{ 0 };
		int32_t horizontalResolution{ 2400 };
		int32_t verticalResolution{ 2400 };
		int32_t colors{ 0 };
		int32_t importantColors{ 0 };
	};

private:
	int data_size{ 0 };
	int width{ 0 };
	int height{ 0 };
	unique_ptr<uint8_t[]> pPixels{ nullptr };

public:
	Bitmap(int width, int height);
	virtual ~Bitmap();

public:
	void fillBitmap(uint8_t, uint8_t, uint8_t);
	void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue);
	bool write(string filename);
};
#pragma pack(pop)

using namespace std;

Bitmap::Bitmap(int width, int height) :
	data_size(width*height*3),
	width(width),
	height(height),
	pPixels( new uint8_t[data_size] { } )
{}	// end Bitmap(int,int)


Bitmap::~Bitmap()
{}


bool Bitmap::write(string filename)
{
	FileHeader fileHeader;
	InfoHeader infoHeader;

	fileHeader.fileSize = sizeof(FileHeader) + sizeof(InfoHeader) + data_size;
	fileHeader.dataOffset = sizeof(FileHeader) + sizeof(InfoHeader);
	infoHeader.width = width;
	infoHeader.height = height;

	ofstream file;
	file.open(filename, ios::out | ios::binary);
	if (!file) return false;

	file.write((char*)&fileHeader, sizeof(fileHeader));
	file.write((char*)&infoHeader, sizeof(infoHeader));
	file.write((char*)pPixels.get(), data_size);
	file.close();

	if (!file)	return false;
	return true;
}

void Bitmap::fillBitmap(uint8_t red, uint8_t green, uint8_t blue)
{
	uint8_t* pPixel = nullptr;
	for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
		{
			pPixel = pPixels.get() + (y * 3) * width + (x * 3);
			pPixel[2] = red;
			pPixel[1] = green;
			pPixel[0] = blue;
		};	// for x
};	// fillBitmap()


void Bitmap::setPixel
(
	int x, int y,
	uint8_t red, uint8_t green, uint8_t blue
)
{
	uint8_t* pPixel = pPixels.get();
	pPixel += (y * 3) * width + (x * 3);
	pPixel[0] = blue;
	pPixel[1] = green;
	pPixel[2] = red;
	return;
};	// setPixel()

int main(int argc, char** argv)
{
	Bitmap bitmap(800, 600);
	bitmap.write("test.bmp");
	bitmap.fillBitmap(128, 128, 128);
	bitmap.write("test128.bmp");
	cout << "Finished." << endl;
	return 0;
}	// main()

 

Postado

acho que sumiu o #include para <iostream>  🤔 

adicionado 4 minutos depois
#pragma pack(push, 2)

Se o bitmap estiver de algum modo corrompido veja como seu compilador implementa esse troço. É pra ser assim em todos mas...

	bitmap.fillBitmap(128, 128, 128);
	bitmap.write("test128.bmp");

para conferir 128 é metade de 256 então isso gera um bitmap com um cinza bem suave.

  • Obrigado 1
Postado

Mais uma coisa:

 

pode ser que seu compilador esteja compilando no padrão C++98 e não em C++11 ou posterior. E nesse caso esse formato de inicialização não é válido

 

header.png.9ca54d43fe228b2ca7a626bc980f864d.png

 

 

Você devia ter desconfiado quando colocou o comentário em reserved... Porque não fez o mesmo na inicialização de header?

 

O outro erro

 

Você não pode escrever 

    header[0] = 'B';
    header[1] = 'M';

em uma declaração de classe porque não há memória alocada para isso. Uma classe é uma classe e uma instância é uma instância.

 

Você pode definir esses valores junto com o resto do header em write() por exemplo. Veja com atenção uma alteração que funcionaria em C++98:

	FileHeader fileHeader;
	InfoHeader infoHeader;

	fileHeader.header[0] = 'B'; // fileHeader e uma instancia da classe
	fileHeader.header[1] = 'M'; // entao pode atribuir valores
	fileHeader.reserved = 0;
	fileHeader.dataOffset = 0;

	fileHeader.fileSize = sizeof(FileHeader) + sizeof(InfoHeader) + data_size;
	fileHeader.dataOffset = sizeof(FileHeader) + sizeof(InfoHeader);
	infoHeader.width = width;
	infoHeader.height = height;

fileHeader é uma instância da classe FileHeader, e aloca memória de acordo. infoHeader é uma instância da classe InfoHeader e aloca memória de acordo. E aí você pode definir os valores como manda o padrão para o formato bitmap.

FileHeader DoisMilDessesHeaders[2000]; // 2.000 instâncias da classe FileHeader

por exemplo aloca espaço para 2000 deles e você pode acessar qualquer um.

 

Desculpe não ter visto antes ou ter anotado no programa. Lembrei por acaso.

 

Um pouco off-topic

 

Sugiro sempre usar o padrão mais recente. Tem muita coisa legal em C++11, 14, 17...

Esses comandos {} são bem interessantes por exemplo

 

Veja esse programa que eu postei ontem neste mesmo forum

#include <iostream> 
#include <vector>

using namespace std;
int main()
{
    std::vector<int> vetor_de_int{ 0,1,2,3,4,5 };
    std::vector<string> vetor_de_string
        {   "muito", "complicado",
            "esse", "lance",
            "de", "template?" };
    cout << "Para um vetor de <int>" << endl;
    for (auto i : vetor_de_int) cout << i << " ";
    cout << endl;
    cout << "Para um vetor de <string>" << endl;
    for (auto i : vetor_de_string) cout << i << " ";
    cout << endl;
    cout << "Vale a pena aprender: economiza muito tempo" << endl;
    return 0;
}

 

Não quero iniciar discussões religiosas, mas de um ponto de vista prático:

  • Visual Studio tendo uma versão community
  • VSCode compilando para Unix em Windows com várias distribuições Linux disponíveis de graça com um click na loja do Windows sem ter que sair do Windows

Ficou difícil justificar o uso de outro ambiente.

 

 

 

  • Obrigado 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!