Здесь я явно упускаю важную концепцию. Я написал код, использующий события мыши, чтобы нарисовать границу (многоугольник) на существующем BufferedImage. Вот соответствующий раздел:
public void paintComponent(Graphics g)
{
super.paintComponent(g); //Paint parent's background
//G3 displays the BufferedImage "Drawing" with each paint
Graphics2D G3 = (Graphics2D)g;
G3.drawImage(this.Drawing, 0, 0, null);
G3.dispose();
}
public void updateDrawing()
{
int x0, y0, x1, y1; // Vertex coordinates
Line2D.Float seg;
// grafix is painting the mouse drawing to the BufferedImage "Drawing"
if (this.pts.size() > 0)
{
for(int ip = 0; ip < pts.size(); ip++)
{
x0 = (int)this.pts.get(ip).x;
y0 = (int)this.pts.get(ip).y;
this.grafix.drawRect(x0 - this.sqw/2, y0 - this.sqh/2, + this.sqw, this.sqh);
if (ip > 0)
{
x1 = (int)this.pts.get(ip-1).x;
y1 = (int)this.pts.get(ip-1).y;
this.grafix.drawLine(x1, y1, x0, y0);
seg = new Line2D.Float(x1, y1, x0, y0);
this.segments.add(seg);
}
}
}
repaint();
}
Следующие две процедуры вызываются событиями мыши: щелчок левой кнопкой мыши приводит к следующей точке, а щелчок правой кнопкой мыши закрывает область.
public void getNextPoint(Point2D p)
{
this.isDrawing = true;
Point2D.Float next = new Point2D.Float();
next.x = (float) p.getX();
next.y = (float) p.getY();
this.pts.add(next);
updateDrawing();
}
public void closeBoundary()
{
//Connects the last point to the first point to close the loop
Point2D.Float next = new Point2D.Float(this.pts.get(0).x, this.pts.get(0).y);
this.pts.add(next);
this.isDrawing = false;
updateDrawing();
}
Все работает нормально, и я могу сохранить изображение с моим рисунком: изображение с рисунком Список вершин (точек) и линейных сегментов (сегментов) - это все, что описывает область / форму / многоугольник. Я хочу извлечь из исходного изображения только ту область, которая находится внутри границы. То есть я планирую создать новое изображение BufferedImage, перемещаясь по всем пикселям, проверяя, попадают ли они в фигуру, и сохраняю их, если они попадают. Итак, я хочу создать ОБЛАСТЬ из точек и сегментов, которые я собрал при рисовании фигуры. Все говорит: создайте переменную AREA и "getPathIterator". Но на какой форме? Моя переменная AREA будет пустой. Как итератор пути получает доступ к точкам в моем списке?
Я просмотрел всю литературу и этот сайт. Я что-то упускаю.




Спасибо haraldK за ваше предложение. Еще до того, как я увидел ваш пост, я пришел к аналогичному выводу: Используя Arraylist вершин из операции рисования, я заполнил объект «Path2D.Float» под названием «contour», пройдя цикл по списку точек, который был создан во время операции «рисования». Используя этот «контурный» объект, я создал объект Area, называемый «интерферограммой». Чтобы проверить свою работу, я создал еще один PathIterator, «PI», из Area и разложил Area, «интерферограмму» на «сегменты», отправив результаты на консоль. Я показываю код ниже:
private void mnuitmKeepInsideActionPerformed(java.awt.event.ActionEvent evt)
{
// Keeps the inner area of interest
// Vertices is the "pts" list from Class MouseDrawing (mask)
// It is already a closed path
ArrayList<Point2D.Float> vertices =
new ArrayList<>(this.mask.getVertices());
this.contour = new Path2D.Float(Path2D.WIND_NON_ZERO);
// Read the vertices into the Path2D variable "contour"
this.contour.moveTo((float)vertices.get(0).getX(),
(float)vertices.get(0).getY()); //Starting location
for(int ivertex = 1; ivertex < vertices.size(); ivertex++)
{
this.contour.lineTo((float)vertices.get(ivertex).getX(),
(float)vertices.get(ivertex).getY());
}
this.interferogram = new Area(this.contour);
PathIterator PI = this.interferogram.getPathIterator(null);
//Test print out the segment types and vertices for debug
float[] p = new float[6];
int icount = 0;
while( !PI.isDone())
{
int type = PI.currentSegment(p);
System.out.print(icount);
System.out.print(" Type " + type);
System.out.print(" X " + p[0]);
System.out.println(" Y " + p[1]);
icount++;
PI.next();
}
BufferedImage masked = Mask(this.image_out, this.interferogram);
// Write image to file for debug
String dir;
dir = System.getProperty("user.dir");
dir = dir + "\\00masked.png";
writeImage(masked, dir, "PNG");
}
Затем я применил маску к изображению, проверяя каждый пиксель на предмет включения в область, используя приведенный ниже код:
public BufferedImage Mask(BufferedImage BIM, Area area)
{
/** Loop through the pixels in the image and test each one for inclusion
* within the area.
* Change the colors of those outside
**/
Point2D p = new Point2D.Double(0,0);
// rgb should be white
int rgb = (255 << 24);
for (int row = 0; row < BIM.getWidth(); row++)
{
for (int col = 0; col < BIM.getHeight(); col++)
{
p.setLocation(col, row);
if (!area.contains(p))
{
BIM.setRGB(col, row, rgb);
}
}
}
return BIM;
}
public static BufferedImage deepCopy(BufferedImage B2M)
{
ColorModel cm = B2M.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = B2M.copyData(B2M.getRaster()
.createCompatibleWritableRaster());
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
Это сработало прекрасно (я был удивлен!), За исключением одной небольшой детали: линии области появлялись снаружи замаскированного изображения. Чтобы исправить это, я скопировал исходное изображение (с измененным размером) перед операцией рисования. Большое спасибо user1050755 (ноябрь 2014 г.) за подпрограмму deepCopy, которую я нашел на этом сайте. Применение моей маски к скопированному изображению привело к тому, что часть исходного изображения, которую я хотел, была без линий маски. Результат показан на прилагаемой картинке. Я в восторге! замаскированное изображение
Сохраните все свои точки во время рисования, затем создайте
Polygonиз точек. При необходимости создайте из негоArea(new Area(polygon)). Но вы также можете создатьPathIteratorпрямо изPolygon. Хотя трудно сказать точно, почему вы этого хотите ... Может быть, вам поможет какой-нибудь псевдокод того, что вы пытаетесь сделать.