mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 18:59:11 +08:00
CURA-4425 improve image quality for some models combined with some viewing angles
This commit is contained in:
parent
0e7edc3eaf
commit
be92bbfcb0
@ -3,6 +3,7 @@
|
|||||||
import numpy
|
import numpy
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
|
from PyQt5.QtGui import QImage
|
||||||
|
|
||||||
from cura.PreviewPass import PreviewPass
|
from cura.PreviewPass import PreviewPass
|
||||||
from cura.Scene import ConvexHullNode
|
from cura.Scene import ConvexHullNode
|
||||||
@ -17,6 +18,21 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
|||||||
|
|
||||||
|
|
||||||
class Snapshot:
|
class Snapshot:
|
||||||
|
@staticmethod
|
||||||
|
def getImageBoundaries(image: QImage):
|
||||||
|
# Look at the resulting image to get a good crop.
|
||||||
|
# Get the pixels as byte array
|
||||||
|
pixel_array = image.bits().asarray(image.byteCount())
|
||||||
|
width, height = image.width(), image.height()
|
||||||
|
# Convert to numpy array, assume it's 32 bit (it should always be)
|
||||||
|
pixels = numpy.frombuffer(pixel_array, dtype=numpy.uint8).reshape([height, width, 4])
|
||||||
|
# Find indices of non zero pixels
|
||||||
|
nonzero_pixels = numpy.nonzero(pixels)
|
||||||
|
min_y, min_x, min_a_ = numpy.amin(nonzero_pixels, axis=1)
|
||||||
|
max_y, max_x, max_a_ = numpy.amax(nonzero_pixels, axis=1)
|
||||||
|
|
||||||
|
return min_x, max_x, min_y, max_y
|
||||||
|
|
||||||
## Return a QImage of the scene
|
## Return a QImage of the scene
|
||||||
# Uses PreviewPass that leaves out some elements
|
# Uses PreviewPass that leaves out some elements
|
||||||
# Aspect ratio assumes a square
|
# Aspect ratio assumes a square
|
||||||
@ -27,6 +43,10 @@ class Snapshot:
|
|||||||
render_width, render_height = active_camera.getWindowSize()
|
render_width, render_height = active_camera.getWindowSize()
|
||||||
render_width = int(render_width)
|
render_width = int(render_width)
|
||||||
render_height = int(render_height)
|
render_height = int(render_height)
|
||||||
|
# Result should have enough resolution; it is cropped and then scaled down.
|
||||||
|
while (render_width < 1000) or (render_height < 1000):
|
||||||
|
render_width *= 2
|
||||||
|
render_height *= 2
|
||||||
preview_pass = PreviewPass(render_width, render_height)
|
preview_pass = PreviewPass(render_width, render_height)
|
||||||
|
|
||||||
root = scene.getRoot()
|
root = scene.getRoot()
|
||||||
@ -50,12 +70,6 @@ class Snapshot:
|
|||||||
# guessed size so the objects are hopefully big
|
# guessed size so the objects are hopefully big
|
||||||
size = max(bbox.width, bbox.height, bbox.depth * 0.5)
|
size = max(bbox.width, bbox.height, bbox.depth * 0.5)
|
||||||
|
|
||||||
# Somehow the aspect ratio is also influenced in reverse by the screen width/height
|
|
||||||
# So you have to set it to render_width/render_height to get 1
|
|
||||||
projection_matrix = Matrix()
|
|
||||||
projection_matrix.setPerspective(30, render_width / render_height, 1, 500)
|
|
||||||
camera.setProjectionMatrix(projection_matrix)
|
|
||||||
|
|
||||||
# Looking from this direction (x, y, z) in OGL coordinates
|
# Looking from this direction (x, y, z) in OGL coordinates
|
||||||
looking_from_offset = Vector(1, 1, 2)
|
looking_from_offset = Vector(1, 1, 2)
|
||||||
if size > 0:
|
if size > 0:
|
||||||
@ -64,19 +78,30 @@ class Snapshot:
|
|||||||
camera.setPosition(look_at + looking_from_offset)
|
camera.setPosition(look_at + looking_from_offset)
|
||||||
camera.lookAt(look_at)
|
camera.lookAt(look_at)
|
||||||
|
|
||||||
|
satisfied = False
|
||||||
|
size = None
|
||||||
|
fovy = 30
|
||||||
|
|
||||||
|
while not satisfied:
|
||||||
|
if size is not None:
|
||||||
|
satisfied = True # always be satisfied after second try
|
||||||
|
projection_matrix = Matrix()
|
||||||
|
# Somehow the aspect ratio is also influenced in reverse by the screen width/height
|
||||||
|
# So you have to set it to render_width/render_height to get 1
|
||||||
|
projection_matrix.setPerspective(fovy, render_width / render_height, 1, 500)
|
||||||
|
camera.setProjectionMatrix(projection_matrix)
|
||||||
preview_pass.setCamera(camera)
|
preview_pass.setCamera(camera)
|
||||||
preview_pass.render()
|
preview_pass.render()
|
||||||
pixel_output = preview_pass.getOutput()
|
pixel_output = preview_pass.getOutput()
|
||||||
|
|
||||||
# Look at the resulting image to get a good crop.
|
min_x, max_x, min_y, max_y = Snapshot.getImageBoundaries(pixel_output)
|
||||||
# Get the pixels as byte array
|
|
||||||
pixel_array = pixel_output.bits().asarray(pixel_output.byteCount())
|
size = max((max_x - min_x) / render_width, (max_y - min_y) / render_height)
|
||||||
# Convert to numpy array, assume it's 32 bit (it should always be)
|
if size > 0.5 or satisfied:
|
||||||
pixels = numpy.frombuffer(pixel_array, dtype=numpy.uint8).reshape([render_height, render_width, 4])
|
satisfied = True
|
||||||
# Find indices of non zero pixels
|
else:
|
||||||
nonzero_pixels = numpy.nonzero(pixels)
|
# make it big and allow for some empty space around
|
||||||
min_y, min_x, min_a_ = numpy.amin(nonzero_pixels, axis=1)
|
fovy *= 0.5 # strangely enough this messes up the aspect ratio: fovy *= size * 1.1
|
||||||
max_y, max_x, max_a_ = numpy.amax(nonzero_pixels, axis=1)
|
|
||||||
|
|
||||||
# make it a square
|
# make it a square
|
||||||
if max_x - min_x >= max_y - min_y:
|
if max_x - min_x >= max_y - min_y:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user