1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Python] How can I get rid of the lines over my drawing? Also how can I reduce the amount of...

Discussão em 'Python' iniciado por Stack, Outubro 3, 2024 às 22:32.

  1. Stack

    Stack Membro Participativo

    Picture with lines over faceI am trying to make a python code that takes an image and converts it into JavaScript so my Blot by Hack Club can read that JS and create that image. Blot documentation Currently my code does that but draws random lines over the code. Also the code generates way to many lines for the blot to handle. How could I find the sweet spot of highest quality with least amount of lines generated

    from PIL import Image, ImageOps
    import numpy as np
    import cv2
    from skimage import measure, transform
    import math

    # Set the detail level (1 for maximum detail, 0 for minimal detail)
    detail_level = 0.4

    # Function to process the image and extract edges with higher precision
    def process_image(image_path):
    # Load image and convert to grayscale
    image = Image.open(image_path).convert("L")
    image = ImageOps.mirror(image) # Mirror the image horizontally
    image = ImageOps.invert(image) # Invert to make the background black and foreground white
    image = image.rotate(180) # Rotate the image by 180 degrees
    image_array = np.array(image)

    # Calculate ksize (ensuring it's odd and positive)
    ksize_value = max(3, int(round(-3.333333333333 * detail_level + 5.666666666666666667)))
    if ksize_value % 2 == 0:
    ksize_value += 1
    ksize = (ksize_value, ksize_value)

    # Apply a slight blur to reduce noise
    blurred = cv2.GaussianBlur(image_array, ksize, 0)

    # Use Canny edge detection with lower thresholds for more sensitivity
    canny_threshold1 = int(round(-33.333333333 * detail_level + 56.6666666666667))
    canny_threshold2 = int(round(-83.33333333 * detail_level + 166.666666667))
    edges = cv2.Canny(blurred, canny_threshold1, canny_threshold2)

    # Optionally, thicken the edges slightly
    edges = transform.rescale(edges, 1.0, anti_aliasing=True)
    edges = cv2.dilate(edges, np.ones((2,2),np.uint8), iterations=1)

    # Use contours to find connected components
    contours = measure.find_contours(edges, 0.8)

    return contours, image_array.shape

    # Function to generate the Blot code
    def generate_blot_code(contours, dimensions, detail_level=0.8, min_distance_threshold=5):
    print("Generating Blot code...")
    lines = []

    # Set a fixed tolerance for fine control over details
    max_tolerance = 0.5 # More detail
    min_tolerance = 0.1 # Minimal simplification
    tolerance = (1 - detail_level) * (max_tolerance - min_tolerance) + min_tolerance

    # Calculate bounding box of all contours
    all_points = np.concatenate(contours)
    min_y, min_x = np.min(all_points, axis=0)
    max_y, max_x = np.max(all_points, axis=0)

    # Calculate scale and translation to center the drawing
    scale_x = (dimensions[1] - 1) / (max_x - min_x)
    scale_y = (dimensions[0] - 1) / (max_y - min_y)
    scale = min(scale_x, scale_y) # Maintain aspect ratio by using the smallest scale factor

    translate_x = (dimensions[1] - (max_x - min_x) * scale) / 2 - min_x * scale
    translate_y = (dimensions[0] - (max_y - min_y) * scale) / 2 - min_y * scale

    # Initialize line counter
    line_counter = 0

    for contour in contours:
    # Smooth the contour and simplify based on the detail level
    smoothed_contour = measure.approximate_polygon(contour, tolerance=tolerance)

    if len(smoothed_contour) >= 2: # Only consider meaningful contours
    prev_x, prev_y = smoothed_contour[0] # Initialize with the first point
    for i in range(1, len(smoothed_contour)):
    y1, x1 = prev_y, prev_x
    y2, x2 = smoothed_contour

    # Scale and translate coordinates
    x1_scaled = int(x1 * scale + translate_x)
    y1_scaled = int(y1 * scale + translate_y)
    x2_scaled = int(x2 * scale + translate_x)
    y2_scaled = int(y2 * scale + translate_y)

    # Calculate the Euclidean distance between consecutive points
    distance = math.sqrt((x2_scaled - x1_scaled) ** 2 + (y2_scaled - y1_scaled) ** 2)

    # Only draw the line if the distance is greater than the threshold
    if distance > min_distance_threshold:
    lines.append(f"finalLines.push([[{x1_scaled}, {y1_scaled}], [{x2_scaled}, {y2_scaled}]]);\n")
    prev_x, prev_y = x2, y2 # Update the previous point to the current point

    # Increment line counter
    line_counter += 1
    if line_counter % 50 == 0:
    lines.append(f"console.log('{line_counter} lines completed');\n")

    blot_code = [
    "// Produced by Aditya Anand's Blotinator, not human-written\n",
    f"setDocDimensions({dimensions[0]}, {dimensions[1]});\n",
    "const finalLines = [];\n"
    ]
    blot_code.extend(lines)
    blot_code.append("drawLines(finalLines);")

    return blot_code

    # Main function
    if __name__ == "__main__":
    # Use the correct image path
    image_path = '/Users/vivaanshahani/Downloads/IMG_9654 3.jpg'
    # Process the image
    contours, dimensions = process_image(image_path)

    # Generate the Blot code with the specified detail level
    blot_code = generate_blot_code(contours, dimensions, detail_level)

    # Write the Blot code to a file
    output_path = "/Users/vivaanshahani/Downloads/Blotcode.js"
    with open(output_path, "w") as file:
    file.writelines(blot_code)

    print(f"Blot code generated and saved to {output_path}")

    Continue reading...

Compartilhe esta Página