Hallo bin Kasialars,
habe ein Prob. bin an einem Projekt wo mein Code ein Objekt einmessen soll. Leider bin ich in der Frage wie ich ein Objekt was per def measure_object ein gemessen werden soll die Rotation setzen muss.
Objekt ist 380x80mm und wird per Scanner ein gelesen. Konturen werden erkannt und messung der Breite wird per def measure_line gemessen. Leider funktioniert die Rotation vom Kontur Rechteck nicht wenn es nicht im Winkel eingemessen wird.
Hier mal ein Codebereich der dafür verantwortlich sein soll:
def measure_object(self, file_path):
try:
# Bild laden
image = cv2.imread(file_path)
# Vorverarbeitung: Glättung mit Gauss-Filter
smoothed = cv2.GaussianBlur(image, (5, 5), 0)
# Graustufenkonvertierung
gray = cv2.cvtColor(smoothed, cv2.COLOR_BGR2GRAY)
# Adaptive Schwellenwerte anwenden
edges = cv2.Canny(gray, 50, 150)
# Morphologische Operationen
kernel = np.ones((3, 3), np.uint8)
edges = cv2.dilate(edges, kernel, iterations=1)
edges = cv2.erode(edges, kernel, iterations=1)
# Konturen finden, aber keine Schließung verwenden (closed=False)
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Filtere Konturen nach ihrer Größe (Bereich)
min_contour_area = 500 # Passen Sie dies an Ihre Anforderungen an
contours = [cnt for cnt in contours if cv2.contourArea(cnt) > min_contour_area]
# Alle Konturen nach ihrem Umfang sortieren
sorted_contours = sorted(contours, key=lambda x: cv2.arcLength(x, closed=True), reverse=True)
# Die Kontur mit dem längsten Umfang auswählen
longest_perimeter_contour = sorted_contours[0]
# Winkel des grünen Rechtecks extrahieren
self.angle = longest_perimeter_contour[2]
print(f"Winkel des grünen Rechtecks: {self.angle} Grad")
# Linienwinkel entsprechend dem Winkel des grünen Rechtecks setzen
self.line_angle = self.angle # oder passen Sie dies nach Ihren Anforderungen an
# Schwerpunkt der Kontur berechnen
M = cv2.moments(longest_perimeter_contour)
cx = int(M["m10"] / M["m00"]) if M["m00"] != 0 else 0
cy = int(M["m01"] / M["m00"]) if M["m00"] != 0 else 0
# Rotation Center setzen
self.rotation_center = (cx, cy)
# Minimal umschließendes Rechteck (Bounding Box) um die Kontur
rect = cv2.minAreaRect(longest_perimeter_contour)
box = cv2.boxPoints(rect)
box = np.intp(box)
# Linienbreite für das Rechteck erhöhen auf 4 Pixel (kann nach Bedarf angepasst werden)
rectangle_thickness = 20
# Die Kontur mit dem längsten Umfang auswählen
x, y, w, h = cv2.boundingRect(longest_perimeter_contour)
cv2.drawContours(image, [box], 0, (0, 255, 0), rectangle_thickness)
# Winkel des grünen Rechtecks
angle = rect[2]
print(f"Winkel des grünen Rechtecks: {angle} Grad")
# Konturapproximation
epsilon = 0.02 * cv2.arcLength(longest_perimeter_contour, True)
longest_contour_approx = cv2.approxPolyDP(longest_perimeter_contour, epsilon, True)
# Messung der Breite und Höhe in Pixeln
width_pixel = w
height_pixel = h
# Umrechnung in Millimeter (angenommene DPI: 200)
dpi = 200
width_mm = width_pixel / dpi * 24.8
height_mm = height_pixel / dpi * 25.35
# Rote waagerechte Linien hinzufügen
middle_measurement_y = y + h // 2
outer_measurement_y1 = y + 200
outer_measurement_y2 = y + h - 200
line_name_middle = "Mitte"
line_name_outer1 = "Links"
line_name_outer2 = "Rechts"
# Übergeben Sie den Winkel des Rechtecks und das Rotationszentrum an die measure_line-Methode
self.measure_line(image, (x, middle_measurement_y), (x + w, middle_measurement_y), width_mm,
line_name_middle, angle, self.rotation_center)
self.measure_line(image, (x, outer_measurement_y1), (x + w, outer_measurement_y1), width_mm,
line_name_outer1, angle, self.rotation_center)
self.measure_line(image, (x, outer_measurement_y2), (x + w, outer_measurement_y2), width_mm,
line_name_outer2, angle, self.rotation_center)
# Berechne prozentuale Deckung der erkannten Kante
coverage_percentage = self.calculate_coverage(edges, (x, y, x + w, y + h))
print(f"Prozentuale Deckung der erkannten Kante: {coverage_percentage:.2f}%")
# Bild verkleinern und anzeigen
target_size = (500, 950)
small_image = cv2.resize(image, target_size)
self.last_image = small_image # Bild für die PDF speichern
self.display_image(small_image)
# Messwerte speichern
self.measurement_data = {
"width_mm": width_mm,
"height_mm": height_mm,
"line_name_outer1": line_name_outer1,
"line_name_middle": line_name_middle,
"line_name_outer2": line_name_outer2,
"coverage_percentage": coverage_percentage
}
# Messwerte in der App anzeigen
self.display_measurement()
except Exception as e:
print(f"Fehler beim Verarbeiten des Bildes: {e}")
def measure_line(self, image, start_point, end_point, width_mm, line_name, angle=None, rotation_center=None):
# ... (vorheriger Code)
# Linienbreite für die roten Linien erhöhen auf 4 Pixel (kann nach Bedarf angepasst werden)
line_thickness = 6
# Falls ein Winkel gegeben ist, rotiere die Start- und Endpunkte
if angle is not None and rotation_center is not None:
print(f"Vor der Rotation - Startpunkt: {start_point}, Endpunkt: {end_point}")
rotated_start_point = self.rotate_point(start_point, angle, rotation_center)
rotated_end_point = self.rotate_point(end_point, angle, rotation_center)
print(
f"Nach der Rotation - Rotierter Startpunkt: {rotated_start_point}, Rotierter Endpunkt: {rotated_end_point}")
start_point = rotated_start_point
end_point = rotated_end_point
# Überprüfen Sie, ob die verschobenen und rotierten Punkte im sichtbaren Bereich liegen
height, width, _ = image.shape
if 0 <= start_point[0] < width and 0 <= start_point[1] < height and 0 <= end_point[0] < width and 0 <= \
end_point[1] < height:
# Nachricht ausgeben
print(f"{line_name} Breite: {width_mm:.2f} mm")
print(f"Rotierter {line_name} - Startpunkt: {start_point}, Endpunkt: {end_point}")
return width_mm
else:
# Wenn die Linie außerhalb des sichtbaren Bereichs liegt, geben Sie einen Fehler aus
print(f"Fehler: {line_name} Linie liegt außerhalb des sichtbaren Bereichs")
return None
def rotate_point(self, point, angle, center):
x, y = point
cx, cy = center
adjusted_x = x - cx
adjusted_y = y - cy
angle_rad = math.radians(angle)
rotated_x = int(adjusted_x * math.cos(angle_rad) - adjusted_y * math.sin(angle_rad))
rotated_y = int(adjusted_x * math.sin(angle_rad) + adjusted_y * math.cos(angle_rad))
rotated_x += cx
rotated_y += cy
print(f"Ursprünglicher Punkt: ({x}, {y})")
print(f"Rotierter Punkt: ({rotated_x}, {rotated_y})")
return rotated_x, rotated_y
def rotate_point(self, point, angle, center):
x, y = point
cx, cy = center
adjusted_x = x - cx
adjusted_y = y - cy
angle_rad = math.radians(angle)
rotated_x = int(adjusted_x * math.cos(angle_rad) - adjusted_y * math.sin(angle_rad))
rotated_y = int(adjusted_x * math.sin(angle_rad) + adjusted_y * math.cos(angle_rad))
rotated_x += cx
rotated_y += cy
return rotated_x, rotated_y
Vielleicht kann mir jemand helfen.
Vielen Dank im voraus.
Grüße
Rotation von Messlinien die sich zu einem Rechteck was nicht im winkel ist mit drehen!
Hier derselbe Code in Code-Tags:
Das macht nicht nur die Fehlersuche leichter, aber manchmal findet man dabei auch selbst schon den Fehler und braucht gar nicht fragen.
Grundsätzlich wäre es schlau, ein möglichst kleines, aber selbständig lauffähiges Beispiel zu bauen, um den Fehler zu verdeutlichen.kasialars hat geschrieben: ↑Donnerstag 25. Januar 2024, 00:07 Hallo bin Kasialars,
habe ein Prob. bin an einem Projekt wo mein Code ein Objekt einmessen soll. Leider bin ich in der Frage wie ich ein Objekt was per def measure_object ein gemessen werden soll die Rotation setzen muss.
Objekt ist 380x80mm und wird per Scanner ein gelesen. Konturen werden erkannt und messung der Breite wird per def measure_line gemessen. Leider funktioniert die Rotation vom Kontur Rechteck nicht wenn es nicht im Winkel eingemessen wird.
Hier mal ein Codebereich der dafür verantwortlich sein soll:Vielleicht kann mir jemand helfen.Code: Alles auswählen
def measure_object(self, file_path): try: # Bild laden image = cv2.imread(file_path) # Vorverarbeitung: Glättung mit Gauss-Filter smoothed = cv2.GaussianBlur(image, (5, 5), 0) # Graustufenkonvertierung gray = cv2.cvtColor(smoothed, cv2.COLOR_BGR2GRAY) # Adaptive Schwellenwerte anwenden edges = cv2.Canny(gray, 50, 150) # Morphologische Operationen kernel = np.ones((3, 3), np.uint8) edges = cv2.dilate(edges, kernel, iterations=1) edges = cv2.erode(edges, kernel, iterations=1) # Konturen finden, aber keine Schließung verwenden (closed=False) contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Filtere Konturen nach ihrer Größe (Bereich) min_contour_area = 500 # Passen Sie dies an Ihre Anforderungen an contours = [cnt for cnt in contours if cv2.contourArea(cnt) > min_contour_area] # Alle Konturen nach ihrem Umfang sortieren sorted_contours = sorted(contours, key=lambda x: cv2.arcLength(x, closed=True), reverse=True) # Die Kontur mit dem längsten Umfang auswählen longest_perimeter_contour = sorted_contours[0] # Winkel des grünen Rechtecks extrahieren self.angle = longest_perimeter_contour[2] print(f"Winkel des grünen Rechtecks: {self.angle} Grad") # Linienwinkel entsprechend dem Winkel des grünen Rechtecks setzen self.line_angle = self.angle # oder passen Sie dies nach Ihren Anforderungen an # Schwerpunkt der Kontur berechnen M = cv2.moments(longest_perimeter_contour) cx = int(M["m10"] / M["m00"]) if M["m00"] != 0 else 0 cy = int(M["m01"] / M["m00"]) if M["m00"] != 0 else 0 # Rotation Center setzen self.rotation_center = (cx, cy) # Minimal umschließendes Rechteck (Bounding Box) um die Kontur rect = cv2.minAreaRect(longest_perimeter_contour) box = cv2.boxPoints(rect) box = np.intp(box) # Linienbreite für das Rechteck erhöhen auf 4 Pixel (kann nach Bedarf angepasst werden) rectangle_thickness = 20 # Die Kontur mit dem längsten Umfang auswählen x, y, w, h = cv2.boundingRect(longest_perimeter_contour) cv2.drawContours(image, [box], 0, (0, 255, 0), rectangle_thickness) # Winkel des grünen Rechtecks angle = rect[2] print(f"Winkel des grünen Rechtecks: {angle} Grad") # Konturapproximation epsilon = 0.02 * cv2.arcLength(longest_perimeter_contour, True) longest_contour_approx = cv2.approxPolyDP(longest_perimeter_contour, epsilon, True) # Messung der Breite und Höhe in Pixeln width_pixel = w height_pixel = h # Umrechnung in Millimeter (angenommene DPI: 200) dpi = 200 width_mm = width_pixel / dpi * 24.8 height_mm = height_pixel / dpi * 25.35 # Rote waagerechte Linien hinzufügen middle_measurement_y = y + h // 2 outer_measurement_y1 = y + 200 outer_measurement_y2 = y + h - 200 line_name_middle = "Mitte" line_name_outer1 = "Links" line_name_outer2 = "Rechts" # Übergeben Sie den Winkel des Rechtecks und das Rotationszentrum an die measure_line-Methode self.measure_line(image, (x, middle_measurement_y), (x + w, middle_measurement_y), width_mm, line_name_middle, angle, self.rotation_center) self.measure_line(image, (x, outer_measurement_y1), (x + w, outer_measurement_y1), width_mm, line_name_outer1, angle, self.rotation_center) self.measure_line(image, (x, outer_measurement_y2), (x + w, outer_measurement_y2), width_mm, line_name_outer2, angle, self.rotation_center) # Berechne prozentuale Deckung der erkannten Kante coverage_percentage = self.calculate_coverage(edges, (x, y, x + w, y + h)) print(f"Prozentuale Deckung der erkannten Kante: {coverage_percentage:.2f}%") # Bild verkleinern und anzeigen target_size = (500, 950) small_image = cv2.resize(image, target_size) self.last_image = small_image # Bild für die PDF speichern self.display_image(small_image) # Messwerte speichern self.measurement_data = { "width_mm": width_mm, "height_mm": height_mm, "line_name_outer1": line_name_outer1, "line_name_middle": line_name_middle, "line_name_outer2": line_name_outer2, "coverage_percentage": coverage_percentage } # Messwerte in der App anzeigen self.display_measurement() except Exception as e: print(f"Fehler beim Verarbeiten des Bildes: {e}") def measure_line(self, image, start_point, end_point, width_mm, line_name, angle=None, rotation_center=None): # ... (vorheriger Code) # Linienbreite für die roten Linien erhöhen auf 4 Pixel (kann nach Bedarf angepasst werden) line_thickness = 6 # Falls ein Winkel gegeben ist, rotiere die Start- und Endpunkte if angle is not None and rotation_center is not None: print(f"Vor der Rotation - Startpunkt: {start_point}, Endpunkt: {end_point}") rotated_start_point = self.rotate_point(start_point, angle, rotation_center) rotated_end_point = self.rotate_point(end_point, angle, rotation_center) print( f"Nach der Rotation - Rotierter Startpunkt: {rotated_start_point}, Rotierter Endpunkt: {rotated_end_point}") start_point = rotated_start_point end_point = rotated_end_point # Überprüfen Sie, ob die verschobenen und rotierten Punkte im sichtbaren Bereich liegen height, width, _ = image.shape if 0 <= start_point[0] < width and 0 <= start_point[1] < height and 0 <= end_point[0] < width and 0 <= \ end_point[1] < height: # Nachricht ausgeben print(f"{line_name} Breite: {width_mm:.2f} mm") print(f"Rotierter {line_name} - Startpunkt: {start_point}, Endpunkt: {end_point}") return width_mm else: # Wenn die Linie außerhalb des sichtbaren Bereichs liegt, geben Sie einen Fehler aus print(f"Fehler: {line_name} Linie liegt außerhalb des sichtbaren Bereichs") return None def rotate_point(self, point, angle, center): x, y = point cx, cy = center adjusted_x = x - cx adjusted_y = y - cy angle_rad = math.radians(angle) rotated_x = int(adjusted_x * math.cos(angle_rad) - adjusted_y * math.sin(angle_rad)) rotated_y = int(adjusted_x * math.sin(angle_rad) + adjusted_y * math.cos(angle_rad)) rotated_x += cx rotated_y += cy print(f"Ursprünglicher Punkt: ({x}, {y})") print(f"Rotierter Punkt: ({rotated_x}, {rotated_y})") return rotated_x, rotated_y def rotate_point(self, point, angle, center): x, y = point cx, cy = center adjusted_x = x - cx adjusted_y = y - cy angle_rad = math.radians(angle) rotated_x = int(adjusted_x * math.cos(angle_rad) - adjusted_y * math.sin(angle_rad)) rotated_y = int(adjusted_x * math.sin(angle_rad) + adjusted_y * math.cos(angle_rad)) rotated_x += cx rotated_y += cy return rotated_x, rotated_y
Vielen Dank im voraus.
Grüße
Das macht nicht nur die Fehlersuche leichter, aber manchmal findet man dabei auch selbst schon den Fehler und braucht gar nicht fragen.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
- __blackjack__
- User
- Beiträge: 13131
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Anmerkung: `rotate_point()` ist zweimal definiert, und das ist eigentlich auch gar keine Methode sondern eine Funktion, die das Objekt gar nicht benötigt. Genau wie `measure_line()` auch eine Funktion ist/sein sollte. Und `measure_line()` ist auch kaputt. Wenn man die ”optionalen” Argumente `angle` und `rotation_center` nicht angibt, liefert die Funktion *implizit* `None` zurück. Das heisst die Argumente sind gar nicht optional. Allerdings benutzt auch keiner der drei Aufrufe den Rückgabewert.
`measure_object()` ist ziemlich lang und die Methode verändert den Zustand des Objekts. Was repräsemtiert dieses Objekt denn überhaupt?
`measure_object()` ist ziemlich lang und die Methode verändert den Zustand des Objekts. Was repräsemtiert dieses Objekt denn überhaupt?
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
Scheint zu passen.... https://www.heise.de/news/Schlechte-Cod ... 09271.html