Home > Mobile >  Change Pixels in image to white Pixels based on list in Python
Change Pixels in image to white Pixels based on list in Python

Time:02-02

In the following code I am trying to straighten a wavy line (white) on a black image with linear regression and want to draw the regression line in a new black image by changing the pixels of the black image to white.

I am doing this by storing the white pixels and using np.polyfit to get a linear function. The resulting x and y values of the regression line are stored in two lists (x_fit and y_fit). Now I want to create a black image with the regression line as white pixels. Therefor I need to switch black pixels to white based on the values in lists x_fit and y_fit.[Original image where the linear regression is performed onThis is the red linear regression line which I want to add to a black picture](https://i.stack.imgur.com/JhBGC.jpg)

Linear regression line in red i want to add to a black image

I am using Python 3.7

I tried to use for loops in line 85 and 86 to change specific black pixles (of x and y values of the linear function) to white in order to display the regression line, but it gives the following error:

Exception has occurred: TypeError list indices must be integers or slices, not numpy.float64

For my understadning i and y are integers and I think that the entries of a list are integers as well, so I dont understand whats wrong.

This is the full code:

from PIL import Image, ImageDraw
import math
import numpy as np
import glob
import matplotlib.pyplot as plt
import imageio.v3 as iio
import skimage.color
import skimage.filters
import cv2
from cv2_plt_imshow import cv2_plt_imshow, plt_format
import glob
import matplotlib.image as img
import csv


img = cv2.imread('canny_cut.jpg') 
image=Image.fromarray(img)

white_pixels = []
height, width, _= img.shape
print('width:  ', width)
print('height: ', height)

# Iterate over all pixels in the image
for x in range(image.width):
    for y in range(image.height):
        pixel = image.getpixel((x, y))
        # If the pixel is white (255), put in array
        if all(z == 255 for z in pixel):
            white_pixels.append((x,y))


x_list= [x[0] for x in white_pixels]
y_list= [y[1] for y in white_pixels]

# creaitng a csv file with white pixels
# Open the file in write mode
with open('white_pixels.csv', 'w', newline='') as csvfile:
    # Create a CSV writer object
    writer = csv.writer(csvfile)
    
    # Write the header row
    writer.writerow(['x', 'y'])
    
    # Iterate over the list of white pixels
    for pixel in white_pixels:
        x, y = pixel
        # Write the x and y coordinates of the pixel to the CSV file
        writer.writerow([x, y])

print(white_pixels[0])
#create polyfit line which gives slope and y-intersection
curve= np.polyfit(x_list,y_list,1)   #gives polynomial function (linear in this case)
print(curve)
print(type(curve))
poly=np.poly1d(curve)
print(poly)

x_fit=[]
y_fit=[]
for i in range(width):
    x_fit.append(i 1)
    calc= poly(i 1)
    y_fit.append(calc)


fig, ax = plt.subplots()
#turn y scale upside down because pixel count starts in upper left corner of image
plt.ylim(height, 0)
plt.xlim(0, width)
ax.plot(x_list,y_list,"-")
ax.plot(x_fit,y_fit,"r-")
plt.show()

print(type(x_list))
print(type(y_list))

# Create new black image - L mode for b/w
reg_img = Image.new( 'L', (width,height))
i=int
y=int
reg_img=np.array(reg_img, dtype=np.uint8)

**# Make white (255) pixels at locations (x_fit, y_fit) 
for i in x_fit:
    for y in y_fit:
        reg_img[x_fit[i], y_fit[y]]=(255,255,255)
cv2.imshow('reg_img', reg_img)**

# Save result
reg_img.save('reg_img.png')

#calculating angle between regression line and x-axis:


P1x=x_fit[0]
P2x=x_fit[len(x_fit)-1]
P1y=y_fit[0]
P2y=y_fit[len(y_fit)-1]
deltaX= P2x-P1x
deltaY= P2y-P2x
angle=np.arctan2([deltaY, deltaX])*180 / np.pi
print(angle)

exit()

The problem is this part of the code:


**# Make white (255) pixels at locations (x_fit, y_fit) 
for i in x_fit:
    for y in y_fit:
        reg_img[x_fit[i], y_fit[y]]=(255,255,255)
cv2.imshow('reg_img', reg_img)**

Line reg_img[x_fit[i], y_fit[y]]=(255,255,255) gives the error:

Exception has occurred: TypeError list indices must be integers or slices, not numpy.float64

CodePudding user response:

"For my understadning i and y are integers and I think that the entries of a list are integers as well" But did you check it? Test x_fit and y_fit element types with x_fit.dtype and y_fit.dtype and then check the sources from which you populate the lists.

Here I think the problem will be that you create "curve" based on np.polyfit which will return an array of floats. You then build the np.poly1d from that which will result in another array of floats

CodePudding user response:

It seemed like the list entries are not integers as assumed. I solved the error by converting the list elements in integers with:

# converting list into integer elements
 x_fit = list(map(int, x_fit))
 y_fit = list(map(int, y_fit))

and replacing the for loops with the following code:

`for x, y in zip(x_fit, y_fit):
      if x< width-1 and y< height-1:
           reg_img[y,x]=255`
  • Related