Il mio approccio generalizza il problema e in effetti cerca un motivo a strisce rosse e bianche (orizzontale o verticale) vicino a una regione blu. Quindi funziona per scene che solo la bandiera americana ha questo schema.
Il mio approccio è sviluppato in Java e utilizza Marvin Framework.
Algoritmo:
- filtro a colori per mantenere solo i pixel dello stesso colore della bandiera americana.
- cerca orizzontale rosso e strisce bianche modello
- Trova verticale rossa e strisce bianche modello
- Rimuovere modelli con piccola area (rumore)
- Verifica se questo modello è circondata da una regione blu
- Segmento zona .
ingresso:

Filtro Colore:

Bandiera:

Più interessante è la performance nel caso ci siano molte bandiere.
ingresso:

Colour Filter:

Pattern Matching:

Bandiera:

Source Code:
import static marvin.MarvinPluginCollection.*;
public class AmericanFlag {
public AmericanFlag(){
process("./res/flags/", "flag_0", Color.yellow);
process("./res/flags/", "flag_1", Color.yellow);
process("./res/flags/", "flag_2", Color.yellow);
process("./res/flags/", "flag_3", Color.yellow);
process("./res/flags/", "flag_4", Color.blue);
}
private void process(String dir, String fileName, Color color){
MarvinImage originalImage = MarvinImageIO.loadImage(dir+fileName+".jpg");
MarvinImage image = originalImage.clone();
colorFilter(image);
MarvinImageIO.saveImage(image, dir+fileName+"_color.png");
MarvinImage output = new MarvinImage(image.getWidth(), image.getHeight());
output.clear(0xFFFFFFFF);
findStripsH(image, output);
findStripsV(image, output);
MarvinImageIO.saveImage(output, dir+fileName+"_1.png");
MarvinImage bin = MarvinColorModelConverter.rgbToBinary(output, 127);
morphologicalErosion(bin.clone(), bin, MarvinMath.getTrueMatrix(5, 5));
morphologicalDilation(bin.clone(), bin, MarvinMath.getTrueMatrix(15, 15));
MarvinImageIO.saveImage(bin, dir+fileName+"_2.png");
int[] centroid = getCentroid(bin);
image.fillRect(centroid[0], centroid[1], 30, 30, Color.yellow);
int area = getMass(bin);
boolean blueNeighbors = hasBlueNeighbors(image, bin, centroid[0], centroid[1], area);
if(blueNeighbors){
int[] seg = getSegment(bin);
for(int i=0; i<4; i++){
originalImage.drawRect(seg[0]+i, seg[1]+i, seg[2]-seg[0], seg[3]-seg[1], color);
}
MarvinImageIO.saveImage(originalImage, dir+fileName+"_final.png");
}
}
private boolean hasBlueNeighbors(MarvinImage image, MarvinImage bin, int centerX, int centerY, int area){
int totalBlue=0;
int r,g,b;
int maxDistance = (int)(Math.sqrt(area)*1.2);
for(int y=0; y<image.getHeight(); y++){
for(int x=0; x<image.getWidth(); x++){
r = image.getIntComponent0(x, y);
g = image.getIntComponent1(x, y);
b = image.getIntComponent2(x, y);
if(
(b == 255 && r == 0 && g == 0) &&
(MarvinMath.euclideanDistance(x, y, centerX, centerY) < maxDistance)
){
totalBlue++;
bin.setBinaryColor(x, y, true);
}
}
}
if(totalBlue > area/5){
return true;
}
return false;
}
private int[] getCentroid(MarvinImage bin){
long totalX=0, totalY=0, totalPixels=0;
for(int y=0; y<bin.getHeight(); y++){
for(int x=0; x<bin.getWidth(); x++){
if(bin.getBinaryColor(x, y)){
totalX += x;
totalY += y;
totalPixels++;
}
}
}
totalPixels = Math.max(1, totalPixels);
return new int[]{(int)(totalX/totalPixels), (int)(totalY/totalPixels)};
}
private int getMass(MarvinImage bin){
int totalPixels=0;
for(int y=0; y<bin.getHeight(); y++){
for(int x=0; x<bin.getWidth(); x++){
if(bin.getBinaryColor(x, y)){
totalPixels++;
}
}
}
return totalPixels;
}
private int[] getSegment(MarvinImage bin){
int x1=-1, x2=-1, y1=-1, y2=-1;
for(int y=0; y<bin.getHeight(); y++){
for(int x=0; x<bin.getWidth(); x++){
if(bin.getBinaryColor(x, y)){
if(x1 == -1 || x < x1){ x1 = x; }
if(x2 == -1 || x > x2){ x2 = x; }
if(y1 == -1 || y < y1){ y1 = y; }
if(y2 == -1 || y > y2){ y2 = y; }
}
}
}
return new int[]{x1,y1,x2,y2};
}
private void findStripsH(MarvinImage imageIn, MarvinImage imageOut){
int strips=0;
int totalPixels=0;
int r,g,b;
int patternStart;
boolean cR=true;
int patternLength = -1;
for(int y=0; y<imageIn.getHeight(); y++){
patternStart = -1;
strips = 0;
patternLength=-1;
for(int x=0; x<imageIn.getWidth(); x++){
r = imageIn.getIntComponent0(x, y);
g = imageIn.getIntComponent1(x, y);
b = imageIn.getIntComponent2(x, y);
if(cR){
if(r == 255 && g == 0 && b == 0){
if(patternStart == -1){ patternStart = x;}
totalPixels++;
} else{
if(patternLength == -1){
if(totalPixels >=3 && totalPixels <= 100){
patternLength = (int)(totalPixels);
} else{
totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
}
} else{
if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
strips++;
totalPixels=1;
cR = false;
} else{
totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
}
}
}
}
else{
if(r == 255 && g == 255 && b == 255){
totalPixels++;
} else{
if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
strips++;
totalPixels=1;
cR = true;
} else{
totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
}
}
}
if(strips >= 4){
imageOut.fillRect(patternStart, y, x-patternStart, 2, Color.black);
totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
}
}
}
}
private void findStripsV(MarvinImage imageIn, MarvinImage imageOut){
int strips=0;
int totalPixels=0;
int r,g,b;
int patternStart;
boolean cR=true;
int patternLength = -1;
for(int x=0; x<imageIn.getWidth(); x++){
patternStart = -1;
strips = 0;
patternLength=-1;
for(int y=0; y<imageIn.getHeight(); y++){
r = imageIn.getIntComponent0(x, y);
g = imageIn.getIntComponent1(x, y);
b = imageIn.getIntComponent2(x, y);
if(cR){
if(r == 255 && g == 0 && b == 0){
if(patternStart == -1){ patternStart = y;}
totalPixels++;
} else{
if(patternLength == -1){
if(totalPixels >=3 && totalPixels <= 100){
patternLength = (int)(totalPixels);
} else{
totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
}
} else{
if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
strips++;
totalPixels=1;
cR = false;
} else{
totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
}
}
}
// if(maxL != -1 && totalPixels > maxL){
// totalPixels=0; patternStart=-1; strips=0; maxL=-1;
// }
}
else{
if(r == 255 && g == 255 && b == 255){
totalPixels++;
} else{
if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
strips++;
totalPixels=1;
cR = true;
} else{
totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
}
}
// if(maxL != -1 && totalPixels > maxL){
// totalPixels=0; patternStart=-1; strips=0; maxL=-1;
// cR=true;
// }
}
if(strips >= 4){
imageOut.fillRect(x, patternStart, 2, y-patternStart, Color.black);
totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
}
}
}
}
private void colorFilter(MarvinImage image){
int r,g,b;
boolean isR, isB;
for(int y=0; y<image.getHeight(); y++){
for(int x=0; x<image.getWidth(); x++){
r = image.getIntComponent0(x, y);
g = image.getIntComponent1(x, y);
b = image.getIntComponent2(x, y);
isR = (r > 120 && r > g * 1.3 && r > b * 1.3);
isB = (b > 30 && b < 150 && b > r * 1.3 && b > g * 1.3);
if(isR){
image.setIntColor(x, y, 255,0,0);
} else if(isB){
image.setIntColor(x, y, 0,0,255);
} else{
image.setIntColor(x, y, 255,255,255);
}
}
}
}
public static void main(String[] args) {
new AmericanFlag();
}
}
Altri Risultati:



Se si dispone di un grande insieme di dati per la formazione, la ricerca di: profonda imparare classificazione delle immagini. Ci sono stati grandi progressi su questo fronte negli ultimi anni. – Photon
So che sei un noto membro di SO, ma sembra che 1) non sia stato fatto alcun tentativo. 2) la domanda è troppo ampia. –
@SalvadorDali, amico ha risposto alla sua domanda qui sotto. Buona risposta anche (ho appena fatto il 16esimo upvotes). Penso che Asker sia aperto a più risposte/approcci però. –