Python实现圆形二维码:如何填充图形线条间的颜色?
Hey there! I totally get how frustrating it is to nail the outline but hit a wall with filling those gaps. Let's break this down and get your circular QR code looking perfect.
First: Let's Talk Library Choices
Matplotlib is great for data plotting, but it's not the most intuitive tool for building and modifying QR codes. For this task, combining the qrcode library (to generate core QR data) with Pillow (PIL) (for image manipulation) will make your life way easier. That said, if you're set on using Matplotlib, we'll cover that too.
Option 1: The Easier Route with Pillow & qrcode
This method generates a standard QR code first, then converts its modules to circles and adds a circular border—no more struggling with path filling!
First, install the required packages:
pip install qrcode[pil]
Then use this code to generate your circular QR code:
import qrcode from PIL import Image, ImageDraw def create_circular_qr(scan_data, output_size=350): # Step 1: Generate a standard QR code qr_generator = qrcode.QRCode( version=2, # Adjust based on how much data you need to store error_correction=qrcode.constants.ERROR_CORRECT_M, # Balances error correction and space box_size=12, border=4, ) qr_generator.add_data(scan_data) qr_generator.make(fit=True) base_qr = qr_generator.make_image(fill_color="black", back_color="white").convert("RGBA") # Step 2: Create a circular mask for the entire QR code circular_mask = Image.new("L", base_qr.size, 0) mask_drawer = ImageDraw.Draw(circular_mask) mask_drawer.ellipse((0, 0, base_qr.size[0], base_qr.size[1]), fill=255) # Step 3: Apply the mask to get a circular outer shape circular_qr = Image.new("RGBA", base_qr.size) circular_qr.paste(base_qr, mask=circular_mask) # Step 4: Replace square modules with circular ones (optional but polished) qr_drawer = ImageDraw.Draw(circular_qr) box_size = qr_generator.box_size border_offset = qr_generator.border * box_size for row_idx, row in enumerate(qr_generator.modules): for col_idx, is_filled in enumerate(row): if is_filled: # Calculate center of the module center_x = border_offset + col_idx * box_size + box_size // 2 center_y = border_offset + row_idx * box_size + box_size // 2 # Draw a circle instead of a square qr_drawer.ellipse( ( center_x - box_size//2, center_y - box_size//2, center_x + box_size//2, center_y + box_size//2 ), fill="black" ) # Save or display your QR code circular_qr.save("my_circular_qr.png") circular_qr.show() # Test it out! create_circular_qr("Your Custom Data Here")
Option 2: Fixing Matplotlib Path Filling
If you want to stick with Matplotlib, the problem is almost certainly that your contour paths aren't closed (start and end points don't meet), or you're using line drawing instead of filled patches.
Here's a quick example of how to draw and fill a closed circular path (adapt this to your QR modules):
import matplotlib.pyplot as plt from matplotlib.patches import PathPatch from matplotlib.path import Path fig, ax = plt.subplots(figsize=(5,5)) # Example closed circular path (replace with your QR module contours) circle_vertices = [ (1, 0), (0.707, 0.707), (0, 1), (-0.707, 0.707), (-1, 0), (-0.707, -0.707), (0, -1), (0.707, -0.707), (1, 0) # Closing the path by repeating the start point ] circle_codes = [Path.MOVETO] + [Path.LINETO]*7 + [Path.CLOSEPOLY] qr_module_path = Path(circle_vertices, circle_codes) filled_patch = PathPatch(qr_module_path, facecolor="black", edgecolor="black") ax.add_patch(filled_patch) # Clean up the plot ax.set_xlim(-1.5, 1.5) ax.set_ylim(-1.5, 1.5) plt.axis("off") plt.show()
Key points here:
- Make sure every contour path ends with
Path.CLOSEPOLYor repeats the starting vertex to close it. - Use
PathPatchwithfacecolorset to your desired fill color instead of just plotting lines.
Final Tips
- If you're drawing custom QR modules from scratch, double-check that each module's outline forms a closed loop—Matplotlib won't fill open shapes.
- The Pillow method is more robust for QR codes because it directly manipulates image pixels, which aligns better with how QR codes are structured.
内容的提问来源于stack exchange,提问作者Fatih YILMAZ




